package com.ybkj.daijia.api.apirest;

import com.ybkj.daijia.serverUtils.HttpClientUtil;
import com.ybkj.daijia.ServiceSetting;
import com.ybkj.daijia.serverUtils.ServiceUtil;
import com.ybkj.daijia.Setting;
import com.ybkj.daijia.serverUtils.SettingUtils;
import com.ybkj.daijia.WxSetting;
import com.ybkj.daijia.api.driver.Error;
import com.ybkj.daijia.api.driver.ErrorConstant;
import com.ybkj.daijia.api.driver.transport.ResultTransport;
import com.ybkj.daijia.api.member.alipay.config.AlipayConfig;
import com.ybkj.daijia.api.member.alipay.sign.MemberOrderSign;
import com.ybkj.daijia.api.member.alipay.sign.RSA;
import com.ybkj.daijia.api.member.alipay.util.AlipayNotify;
import com.ybkj.daijia.api.unionpay.AcpService;
import com.ybkj.daijia.api.unionpay.DemoBase;
import com.ybkj.daijia.api.unionpay.LogUtil;
import com.ybkj.daijia.api.unionpay.SDKConfig;
import com.ybkj.daijia.api.unionpay.SDKConstants;
import com.ybkj.daijia.api.util.ErrorConstantV4;
import com.ybkj.daijia.api.weixin.tenpayv3.Configuration;
import com.ybkj.daijia.api.weixin.tenpayv3.GetWxOrderno;
import com.ybkj.daijia.api.weixin.tenpayv3.RequestHandler;
import com.ybkj.daijia.api.weixin.tenpayv3.Sha1Util;
import com.ybkj.daijia.api.weixin.tenpayv3.TenpayUtil;
import com.ybkj.daijia.common.FileUploadVo;
import com.ybkj.daijia.common.Result;
import com.ybkj.daijia.server.controller.CommonController;
import com.ybkj.daijia.server.errand.Order;
import com.ybkj.daijia.server.errand.OrderTemp;
import com.ybkj.daijia.server.errand.OrderType;
import com.ybkj.daijia.server.errand.OrderUp;
import com.ybkj.daijia.server.errand.OrderUp.PayTypeDetails;
import com.ybkj.daijia.server.errand.PayRecordOrder;
import com.ybkj.daijia.server.errand.PayRecordOrder.PayRecordTypeOrder;
import com.ybkj.daijia.server.errand.SelectPrice;
import com.ybkj.daijia.server.event.model.OrderPassengerHasPayEvent;
import com.ybkj.daijia.server.event.model.errand.ErrandOrderUpCancelEvent;
import com.ybkj.daijia.server.event.model.errand.ErrandOrderUpConfirmEvent;
import com.ybkj.daijia.server.event.model.errand.ErrandOrderUpRunEvent;
import com.ybkj.daijia.server.event.model.errand.PaotuiOrderUpAcceptEvent;
import com.ybkj.daijia.server.event.model.errand.PaotuiOrderUpCreateEvent;
import com.ybkj.daijia.server.event.model.errand.PaotuiOrderUpRecordEvent;
import com.ybkj.daijia.server.mc.Enterprise;
import com.ybkj.daijia.server.mc.Passenger;
import com.ybkj.daijia.server.mc.PassengerAccount;
import com.ybkj.daijia.server.mc.PassengerGrade;
import com.ybkj.daijia.server.model.Area;
import com.ybkj.daijia.server.model.AreaWeight;
import com.ybkj.daijia.server.model.ChargeStartWeight;
import com.ybkj.daijia.server.model.ChargeWeightDistance;
import com.ybkj.daijia.server.model.Company;
import com.ybkj.daijia.server.model.Driver;
import com.ybkj.daijia.server.model.DriverRefuseRecord;
import com.ybkj.daijia.server.sales.Coupon;
import com.ybkj.daijia.server.sales.CouponRule;
import com.ybkj.daijia.server.sales.CouponRule.CouponType;
import com.ybkj.daijia.server.service.AreaService;
import com.ybkj.daijia.server.service.CompanyService;
import com.ybkj.daijia.server.service.CouponService;
import com.ybkj.daijia.server.service.DriverRefuseRecordService;
import com.ybkj.daijia.server.service.DriverService;
import com.ybkj.daijia.server.service.ErrandUpService;
import com.ybkj.daijia.server.service.FreightService;
import com.ybkj.daijia.server.service.MemberService;
import com.ybkj.daijia.server.service.OrderService;
import com.ybkj.daijia.server.service.ZhuancheService;
import com.ybkj.daijia.server.service.ZhuanxianService;
import com.ybkj.daijia.server.websocket.WebSocketSend;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.SortedMap;
import java.util.TreeMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.ApplicationEventMulticaster;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.util.WebUtils;

@Controller("ApiErrandProcessUpController")
@RequestMapping(value = "api/errand/up")
public class ErrandUpProcessController {

    private static final Logger logger = LoggerFactory
        .getLogger(ErrandUpProcessController.class);

    @Autowired
    private SettingUtils settingUtils;
    @Autowired
    private ErrandUpService errandService;
    @Autowired
    private MemberService memberService;
    @Autowired
    private AreaService areaService;
    @Autowired
    private CompanyService companyService;
    @Autowired
    private DriverService driverService;
    @Autowired
    private DriverRefuseRecordService driverRefuseRecordService;
    @Autowired
    private ApplicationEventMulticaster applicationEventMulticaster;
    @Autowired
    private CouponService couponService;
    @Autowired
    private OrderService orderService;
    @Autowired
    private ZhuancheService zhuancheService;
    @Autowired
    private FreightService freightService;
    @Autowired
    private ZhuanxianService zhuanxianService;

    /**
     * 获取请求参数中所有的信息.
     *
     * @param request
     * @return
     */
    public static Map<String, String> getAllRequestParam(
        final HttpServletRequest request) {
        Map<String, String> res = new HashMap<String, String>();
        Enumeration<?> temp = request.getParameterNames();
        if (null != temp) {
            while (temp.hasMoreElements()) {
                String en = (String) temp.nextElement();
                String value = request.getParameter(en);
                res.put(en, value);
                // 在报文上送时，如果字段的值为空，则不上送<下面的处理为在获取所有参数数据时，判断若值为空，则删除这个字段>
                if (null == res.get(en) || "".equals(res.get(en))) {
                    res.remove(en);
                }
            }
        }
        return res;
    }

    @RequestMapping(value = "pushCancelOrder")
    public @ResponseBody
    void pushCancelOrder(Long orderId) {
        try {
            if (null != orderId) {
                OrderUp order = errandService.findOne(orderId);
                if (null != order) {
                    Driver driver = new Driver();
                    if (null != order.getEmployId()) {
                        driver = driverService.findOne(order.getEmployId());
                        if (null != driver) {

                            Long amount = errandService.countBusyAmount(driver
                                .getId());
                            if (amount == 0) {
                                if (driver.getStatus() != Driver.DRIVER_OFFLINE) {
                                    driverService.updateStatusAndJobStatus(
                                        Driver.DRIVER_ONLINE, null,
                                        driver.getId());
                                }
                            }
                        }
                    }
                    // 添加退款信息
                    try {
                        errandService.backMoney(orderId);
                        ;
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    ErrandOrderUpCancelEvent cancelEvent = new ErrandOrderUpCancelEvent(
                        order, driver, "customerCancel");
                    applicationEventMulticaster.multicastEvent(cancelEvent);
                }
            }
        } catch (Exception e) {
            logger.error("push error : " + e.getMessage());
        }
    }

    @RequestMapping(value = "pushRunOrder")
    public @ResponseBody
    void pushRunOrder(Long orderId) {
        try {
            if (null != orderId) {
                OrderUp order = errandService.findOne(orderId);
                if (null != order && null != order.getEmployId()) {
                    Driver driver = driverService.findOne(order.getEmployId());
                    if (null != driver) {
                        Passenger passenger = memberService
                            .findOnePassenger(order.getPassengerId());
                        ErrandOrderUpRunEvent runEvent = new ErrandOrderUpRunEvent(
                            order, passenger);
                        applicationEventMulticaster.multicastEvent(runEvent);
                    }
                }
            }
        } catch (Exception e) {
            logger.error("push error : " + e.getMessage());
        }
    }

    @RequestMapping(value = "pushNewOrder")
    public @ResponseBody
    void pushNewOrder(Long orderId) {
        try {
            OrderUp order = errandService.findOne(orderId);
            PaotuiOrderUpCreateEvent paotuiOrderCreateEvent = new PaotuiOrderUpCreateEvent(
                order);
            applicationEventMulticaster.multicastEvent(paotuiOrderCreateEvent);

            PaotuiOrderUpRecordEvent orderRecordEvent = new PaotuiOrderUpRecordEvent(
                order);
            applicationEventMulticaster.multicastEvent(orderRecordEvent);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 预估跑腿价格(根据时间和距离)
    @RequestMapping(value = "getNewPrice")
    public @ResponseBody
    Map<String, Object> getNewPrice(
        @RequestParam("passengerId") Long passengerId,
        @RequestParam("city") String city,
        @RequestParam(required = false, value = "acKey") String acKey,
        @RequestParam("time") Integer time,
        @RequestParam("mileage") Double mileage) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            Area area = null;
            if (StringUtils.isNotBlank(acKey)) {
                Company company = companyService.findByAppKey(acKey);
                if (company != null) {
                    area = areaService.findOneWithCharge(company
                        .getAreaPaotuiId());
                }
            }
            Passenger passenger = memberService.findOnePassenger(passengerId);
            if (null != passenger) {
                if (null == area) {
                    Company finalCompany = null;// 最终决定公司
                    Area paotuiArea = null;
                    if (passenger.getType().equals(Passenger.TYPE_PASSENGER)) {
                        paotuiArea = areaService
                            .findPaotuiByPassenger(passenger.getId());
                    } else if (passenger.getType().equals(
                        Passenger.TYPE_ENTERPRISE)) {
                        paotuiArea = areaService
                            .findPaotuiByEnterprise(passenger
                                .getEnterprise_id());
                    }
                    if (null != paotuiArea) {
                        area = areaService
                            .findOneWithCharge(paotuiArea.getId());
                    } else {
                        List<Company> companys = companyService
                            .findByAreaCityName(city);
                        if (!CollectionUtils.isEmpty(companys)) {
                            for (Company company : companys) {
                                if (company.getId().equals(
                                    passenger.getCompanyId())) {
                                    finalCompany = company;
                                    break;
                                }
                            }

                            List<Company> notMainCompanys = new ArrayList<Company>();
                            Company cityMainCompany = null;

                            if (null == finalCompany) {
                                for (Company company : companys) {
                                    if (!company.isCompanyType()) {
                                        if (StringUtils.isBlank(company
                                            .getAppKey())) {
                                            notMainCompanys.add(company);
                                        }
                                    } else {
                                        cityMainCompany = company;
                                    }
                                }
                                if (!CollectionUtils.isEmpty(notMainCompanys)) {
                                    finalCompany = notMainCompanys
                                        .get(new Random()
                                            .nextInt(notMainCompanys
                                                .size()));
                                }
                            }
                            if (null == finalCompany) {
                                if (null != cityMainCompany) {
                                    finalCompany = cityMainCompany;
                                }
                            }
                        }
                        if (null == finalCompany) {
                            finalCompany = companyService.findOne(passenger
                                .getCompanyId());
                        }
                        area = areaService.findOneWithCharge(finalCompany
                            .getAreaPaotuiId());
                    }
                }
                Integer time2 = time * 60;
                map = errandService.getPrice(area, mileage, time2);

            } else {
                map.put("success", false);
                map.put("message", "客户不存在");
            }
        } catch (Exception e) {
            e.printStackTrace();
            map.put("success", false);
            map.put("message", "内部服务器错误");
        }
        return map;
    }

    // 预算费用(areaId,经纬度)
    @RequestMapping(value = "getPriceByAreaId")
    public @ResponseBody
    Map<String, Object> getPriceByAreaId(
        @RequestParam(required = true, value = "areaId") Long areaId,
        @RequestParam(required = true, value = "startLat") Double startLat,
        @RequestParam(required = true, value = "startLng") Double startLng,
        @RequestParam(required = false, value = "endLat") Double endLat,
        @RequestParam(required = false, value = "endLng") Double endLng) {

        Map<String, Object> map = new HashMap<String, Object>();
        try {
            Double mileage = 0.0;
            Integer time = 0;
            if (startLat != null && startLng != null && endLat != null
                && endLng != null) {
                Result<Map<String, Long>> result = HttpClientUtil
                    .getDistanceAndTimeValueByTwoPoints(startLng, startLat,
                        endLng, endLat);
                Map<String, Long> result2 = result.getResult();
                Long distance = result2.get("distance");// 米
                Long timemis = result2.get("time");// 秒
                time = (int) (timemis / 60);
                mileage = (double) (distance / 1000);
            }
            Map<String, Object> map2 = errandService.getNewPrice(areaId,
                mileage, time);
            if ((Boolean) map2.get("success")) {
                Map<String, Object> data = new HashMap<String, Object>();
                data.put("money", map2.get("money"));
                data.put("mileage", mileage);
                data.put("time", time);
                data.put("startPrice", map2.get("startPrice"));
                data.put("mileagePrice", map2.get("mileagePrice"));
                data.put("travelTimePrice", map2.get("travelTimePrice"));
                data.put("pay_detail", map2.get("pay_detail"));
                map.put("data", data);
                map.put("success", true);
                map.put("message", map2.get("message"));
                map.put("code", 0);
            } else {
                map.put("success", false);
                map.put("code", -42);
                map.put("message", map2.get("message"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            map.put("code", -42);
            map.put("message", "预算失败");
        }
        return map;
    }

    // 预估跑腿价格
    @RequestMapping(value = "getPrice")
    public @ResponseBody
    Map<String, Object> getPrice(Long passengerId,
        String city, String acKey, Double startLat, Double startLng,
        Double endLat, Double endLng) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            Area area = null;
            if (StringUtils.isNotBlank(acKey)) {
                Company company = companyService.findByAppKey(acKey);
                if (company != null) {
                    area = areaService.findOneWithCharge(company
                        .getAreaPaotuiId());
                }
            }
            Passenger passenger = memberService.findOnePassenger(passengerId);
            if (null != passenger) {
                if (null == area) {
                    Company finalCompany = null;// 最终决定公司
                    Area paotuiArea = null;
                    if (passenger.getType().equals(Passenger.TYPE_PASSENGER)) {
                        paotuiArea = areaService
                            .findPaotuiByPassenger(passenger.getId());
                    } else if (passenger.getType().equals(
                        Passenger.TYPE_ENTERPRISE)) {
                        paotuiArea = areaService
                            .findPaotuiByEnterprise(passenger
                                .getEnterprise_id());
                    }
                    if (null != paotuiArea) {
                        area = areaService
                            .findOneWithCharge(paotuiArea.getId());
                    } else {
                        List<Company> companys = companyService
                            .findByAreaCityName(city);
                        if (!CollectionUtils.isEmpty(companys)) {
                            for (Company company : companys) {
                                if (company.getId().equals(
                                    passenger.getCompanyId())) {
                                    finalCompany = company;
                                    break;
                                }
                            }

                            List<Company> notMainCompanys = new ArrayList<Company>();
                            Company cityMainCompany = null;

                            if (null == finalCompany) {
                                for (Company company : companys) {
                                    if (!company.isCompanyType()) {
                                        if (StringUtils.isBlank(company
                                            .getAppKey())) {
                                            notMainCompanys.add(company);
                                        }
                                    } else {
                                        cityMainCompany = company;
                                    }
                                }
                                if (!CollectionUtils.isEmpty(notMainCompanys)) {
                                    finalCompany = notMainCompanys
                                        .get(new Random()
                                            .nextInt(notMainCompanys
                                                .size()));
                                }
                            }
                            if (null == finalCompany) {
                                if (null != cityMainCompany) {
                                    finalCompany = cityMainCompany;
                                }
                            }
                        }
                        if (null == finalCompany) {
                            finalCompany = companyService.findOne(passenger
                                .getCompanyId());
                        }
                        area = areaService.findOneWithCharge(finalCompany
                            .getAreaPaotuiId());
                    }
                }
                Result<Map<String, Long>> result = HttpClientUtil
                    .getDistanceAndTimeValueByTwoPoints(startLng, startLat,
                        endLng, endLat);
                Map<String, Long> result2 = result.getResult();
                Double distance = Double.valueOf(result2.get("distance"));// 米
                Integer time = Integer.getInteger(result2.get("time")
                    .toString());// 秒
                map = errandService.getPrice(area, distance / 1000, time * 60);

            } else {
                map.put("success", false);
                map.put("message", "客户不存在");
            }
        } catch (Exception e) {
            e.printStackTrace();
            map.put("success", false);
            map.put("message", "内部服务器错误");
        }
        return map;
    }

    @RequestMapping(value = "pushAcceptOrder")
    public @ResponseBody
    void pushAcceptOrder(Long orderId) {
        try {
            if (null != orderId) {
                OrderUp order = errandService.findOne(orderId);
                if (null != order) {
                    Driver driver = driverService.findOne(order.getEmployId());
                    if (null != driver) {

                        if (driver.getStatus() != Driver.DRIVER_OFFLINE) {
                            driverService.updateStatusAndJobStatus(
                                Driver.DRIVER_BUSY,
                                Driver.DRIVER_JOBSTATUS_PAOTUI,
                                order.getEmployId());
                        }

                        PaotuiOrderUpAcceptEvent acceptEvent = new PaotuiOrderUpAcceptEvent(
                            order, driver);
                        applicationEventMulticaster.multicastEvent(acceptEvent);
                    }
                }
            }
        } catch (Exception e) {
            logger.error("push error : " + e.getMessage());
        }
    }

    @RequestMapping(value = "pushRefuseOrder")
    public @ResponseBody
    void pushRefuseOrder(Long orderId, Long employId,
        String content) {
        try {
            if (null != orderId) {
                OrderUp order = errandService.findOne(orderId);
                if (null != order && null != employId) {
                    Driver driver = driverService.findOne(employId);
                    if (null != driver) {
                        Long amount = errandService.countBusyAmount(driver
                            .getId());
                        if (amount == 0) {
                            if (driver.getStatus() != Driver.DRIVER_OFFLINE) {
                                driverService.updateStatusAndJobStatus(
                                    Driver.DRIVER_ONLINE, null,
                                    driver.getId());
                            }
                        }
                        // 拒绝工单记录
                        DriverRefuseRecord driverRefuseRecord = new DriverRefuseRecord();
                        driverRefuseRecord.setEmployId(driver.getId());
                        driverRefuseRecord.setEmployRealName(driver
                            .getRealname());
                        driverRefuseRecord.setEmployUserName(driver
                            .getUsername());
                        driverRefuseRecord.setEmployPhone(driver.getPhone());
                        driverRefuseRecord.setHappend(new Date());
                        driverRefuseRecord.setOrderId(order.getId());
                        driverRefuseRecord.setOrderNumber(order.getOrderNo());
                        driverRefuseRecord.setOrderCompanyId(order
                            .getCompanyId());
                        driverRefuseRecord.setMemo(content);
                        driverRefuseRecord
                            .setOrderType(DriverRefuseRecord.OrderType.paotui);
                        driverRefuseRecordService.save(driverRefuseRecord);
                    }
                }
            }
        } catch (Exception e) {
            logger.error("push error : " + e.getMessage());
        }
    }

    @RequestMapping(value = "hurryOrder")
    public @ResponseBody
    void hurryOrder(Long orderId) {
        try {
            Company orderCompany = null;
            OrderUp order = errandService.findOne(orderId);
            if (null != order) {
                orderCompany = companyService.findOne(order.getCompanyId());
                if (null != orderCompany) {

                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("passengerName", order.getPassengerName());
                    jsonObject.put("orderId", order.getId());
                    jsonObject.put("orderNo", order.getOrderNo());
                    jsonObject.put("type", "hurryOrder_company");

                    jsonObject.put("status", order.getStatus());
                    jsonObject.put("startLng", order.getStartLng());
                    jsonObject.put("startLat", order.getStartLat());
                    jsonObject.put("id", order.getId());
                    jsonObject.put("startAddress", order.getStartAddress());
                    jsonObject.put("passengerPhone", order.getPassengerPhone());

                    Company mainCompany = companyService.getMain();
                    WebSocketSend.boardcastToCompany(jsonObject,
                        orderCompany.getId(), mainCompany.getId());

                }
            }

        } catch (Exception e) {

        }

    }

    @RequestMapping(value = "getEmployStatus")
    public @ResponseBody
    Map<String, Object> getEmployStatus(Long driverId) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("success", false);
        if (null != driverId) {
            Driver driver = driverService.findOne(driverId);
            if (null != driver) {
                map.put("status", driver.getStatus());
                if (null != driver.getJobStatus()) {
                    map.put("jobStatus", driver.getJobStatus());
                } else {
                    map.put("jobStatus", -1);
                }
                map.put("success", true);
            }
        }
        return map;
    }

    // 上传图片
    @RequestMapping(value = "uploadErrandImg", method = RequestMethod.GET)
    public @ResponseBody
    ResultTransport uploadErrandImg(
        HttpServletRequest req, @RequestParam("imgUrl") String imgUrl,
        @RequestParam("orderId") Long orderId) {
        CommonController common = new CommonController();
        FileUploadVo vo = null;
        try {
            Long datetime = System.currentTimeMillis();
            String imgurl = "";
            Map<String, Object> map = new HashMap<String, Object>();

            File newFile = new File(WebUtils.getRealPath(req.getSession()
                .getServletContext(), "/")
                + "/upload/errand/temp" + datetime + "_" + orderId + ".jpg");

            FileUtils.copyURLToFile(new URL(imgUrl), newFile);

            vo = common.uploadErrandImg2(newFile, req);

            if (newFile.exists()) {
                newFile.delete();
            }

            imgurl = vo.getUrl() + "-" + vo.getMinurl();
            ResultTransport instance = ResultTransport
                .getErrorBy(ErrorConstant.SUCCESS);
            map.put("imgurl", imgurl);
            map.put("orderId", orderId);
            instance.setData(map);

            return instance;
        } catch (Exception e) {
            logger.error("api v3 driver uploadErrandImg error: {}", e);
            e.printStackTrace();
            return ResultTransport.getErrorBy(ErrorConstant.SERVER_ERROR);
        }
    }

    public String uploadErrandImg(HttpServletRequest req,
        MultipartFile imgFile, int randNum) {

        String imgurl = "";
        try {
            Long datetime = System.currentTimeMillis();
            File tempDest = new File(WebUtils.getRealPath(req.getSession()
                .getServletContext(), "/")
                + "/upload/errand/temp" + datetime + "_" + randNum + ".jpg");
            imgFile.transferTo(tempDest);

            CommonController common = new CommonController();
            FileUploadVo vo = common.uploadErrandImg2(tempDest, req);

            if (tempDest.exists()) {
                tempDest.delete();
            }

            imgurl = vo.getUrl() + "-" + vo.getMinurl();

        } catch (Exception e) {
            e.printStackTrace();
        }

        return imgurl;

    }

    @RequestMapping(value = "queryErrandDriver", method = RequestMethod.GET)
    public @ResponseBody
    Map<String, Object> queryErrandDriver(
        @RequestParam(required = false, value = "companyId") Long companyId,
        @RequestParam(required = false, value = "scope") Double distance,
        @RequestParam("lng") Double lng, @RequestParam("lat") Double lat) {
        if (distance == null) {
            distance = 5.0;// 默认5公里
        }
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("code", 0);
        map.put("message", "成功");
        List<Driver> errandListDrivers = driverService.errandListDrivers(lng,
            lat, distance);

        List<Map<String, Object>> mapData = new ArrayList<Map<String, Object>>();
        for (Driver d : errandListDrivers) {
            Map<String, Object> m = new HashMap<String, Object>();
            Integer driverStatus = d.getStatus();
            Double latitude = d.getLastLatitude();
            if (null == latitude) {
                latitude = d.getLatitude();
            }
            Double longitude = d.getLastLongitude();
            if (null == longitude) {
                longitude = d.getLongitude();
            }
            m.put("driverStatus", driverStatus);
            m.put("driverLat", latitude);
            m.put("driverLng", longitude);
            mapData.add(m);
        }
        map.put("data", mapData);
        return map;

        // 为什么查询附近服务人员要分公司？
        // if(companyId!=null){
        // List<Map<String,Object>> mapData=new ArrayList<Map<String,Object>>();
        // for(Driver d : errandListDrivers){
        // if(companyId.equals(d.getCompanyId())){
        // Map<String,Object> m=new HashMap<String, Object>();
        // Integer driverStatus = d.getStatus();
        // Double latitude = d.getLastLatitude();
        // if(null==latitude){
        // latitude=d.getLatitude();
        // }
        // Double longitude = d.getLastLongitude();
        // if(null==longitude){
        // longitude=d.getLongitude();
        // }
        // m.put("driverStatus", driverStatus);
        // m.put("driverLat", latitude);
        // m.put("driverLng", longitude);
        // mapData.add(m);
        // }
        // }
        //
        // map.put("data", mapData);
        // return map;
        // }else{
        // for(Driver d : errandListDrivers){
        // Integer driverStatus = d.getStatus();
        // Double latitude = d.getLastLatitude();
        // if(null==latitude){
        // latitude=d.getLatitude();
        // }
        // Double longitude = d.getLastLongitude();
        // if(null==longitude){
        // longitude=d.getLongitude();
        // }
        // d.setDriverStatus(driverStatus);
        // d.setDriverLat(latitude);
        // d.setDriverLng(longitude);
        // }
        // map.put("data", errandListDrivers);
        // return map;
        // }
    }

    @RequestMapping(value = "listValidCouponsByPassenger", method = RequestMethod.GET)
    public @ResponseBody
    Map<String, Object> listValidCouponsByPassenger(
        @RequestParam(required = true, value = "passengerId") Long passengerId,
        @RequestParam(required = false, value = "couponTypeId") Long couponTypeId) {

        Map<String, Object> map = new HashMap<String, Object>();

        List<Map<String, Object>> couponMapList = new ArrayList<Map<String, Object>>();

        List<Coupon> coupons = couponService
            .listByPassenger(passengerId, CouponType.paotui, couponTypeId, null);
        if (!CollectionUtils.isEmpty(coupons)) {
            for (Coupon coupon : coupons) {
                CouponRule rule = coupon.getCouponRule();
                Map<String, Object> couponMap = new HashMap<String, Object>();
                couponMap.put("couponId", coupon.getId());
                couponMap.put("couponType", rule.getType());
                couponMap.put("couponTypeId", rule.getCouponTypeId());
                if (null != rule.getCouponTypeId()) {
                    OrderType orderType = errandService.findByTypeId(rule
                        .getCouponTypeId());
                    if (null != orderType) {
                        couponMap
                            .put("couponTypeName", orderType.getTypeName());
                    }
                }
                couponMap.put("couponMoney", rule.getMoney());
                couponMap.put("couponDiscount", rule.getDiscount());
                couponMap.put("couponCode", coupon.getCode());
                couponMap.put("couponTitle", rule.getTitle());
                couponMap.put("startTime", rule.getStart().getTime());
                if (null != rule.getEnd()) {
                    couponMap.put("endTime", rule.getEnd().getTime());
                } else {
                    couponMap.put("endTime", null);
                }
                couponMapList.add(couponMap);
            }
        }
        map.put("code", 0);
        map.put("data", couponMapList);
        map.put("msg", "成功");
        return map;
    }

    /**
     * V2获取页面数据
     *
     * @param orderId
     * @return
     */
    @RequestMapping(value = "clientPayData", method = RequestMethod.GET)
    public @ResponseBody
    Map<String, Object> clientPayData(Long orderId) {

        Map<String, Object> map = new HashMap<String, Object>();

        Setting setting = settingUtils.get();

        OrderUp order = errandService.findOne(orderId);

        BigDecimal coupon_hasPayed = new BigDecimal(order.getCouponMoney());
        map.put("realCash", new BigDecimal(order.getRealPay()));//结算费用
        map.put("goodsCash",
            order.getGoodsCash() != null ? order.getGoodsCash() : 0);
        map.put("thanksCash",
            order.getThanksCash() != null ? order.getThanksCash() : 0);
        map.put("guoluMoney",
            order.getGuoluMoney() != null ? order.getGuoluMoney() : 0);
        map.put("yuanchengMoney",
            order.getYuanchengMoney() != null ? order.getYuanchengMoney()
                : 0);
        map.put("otherMoney",
            order.getOtherMoney() != null ? order.getOtherMoney() : 0);
        map.put("weightPrice",
            order.getWeightPrice() != null ? order.getWeightPrice() : 0);
        map.put("czMoney", order.getCzMoney() != null ? order.getCzMoney() : 0);
        map.put("protectPrice",
            order.getProtectPrice() != null ? order.getProtectPrice() : 0);
        map.put("travelTimeMoney",
            order.getTravelTimePrice() != null ? order.getTravelTimePrice()
                : 0);
        map.put("travelTime",
            order.getTravelTime() != null ? order.getTravelTime() : 0);
        map.put("waitedTime",
            order.getWaitedTime() != null ? order.getWaitedTime() : 0);
        map.put("waitPrice",
            order.getWaitPrice() != null ? order.getWaitPrice() : 0);
        String remark = "";
        if (null != order.getMemoList() && order.getMemoList().size() > 0) {
            for (int i = 0; i < order.getMemoList().size(); i++) {
                remark += order.getMemoList().get(i).getMemo() + ",";
            }
        }
        remark += order.getEmployMemo();
        String weightPriceContent = "";
        if (null != order.getWeight() && null != order.getAreaWeightId()) {
            AreaWeight areaWeight = areaService.findOneWeight(order
                .getAreaWeightId());
            if (null != areaWeight) {
                // 获取重量收费标准
                BigDecimal money = BigDecimal.ZERO;
                SelectPrice selectPrice = new SelectPrice();
                selectPrice.setWeightPrice(order.getWeight(), areaWeight);

                ChargeStartWeight price = selectPrice.getwPrice();
                money = selectPrice.shouldCash;
                if (null == money) {
                    money = BigDecimal.ZERO;
                }
                StringBuilder builder = new StringBuilder();
                List<ChargeWeightDistance> distances = price
                    .getChargeWeightDistances();

                if (distances != null && distances.size() != 0) {
                    for (ChargeWeightDistance d : distances) {
                        builder.append(d.getStartdistance() + "KG到"
                            + d.getDistance() + "KG内,加收" + d.getMoney()
                            + "元");
                        builder.append("\n");
                    }
                }

                builder.append("超过" + price.getStartWeight() + "KG");
                builder.append("以后每" + price.getOverWeight() + "KG");
                builder.append("加收" + price.getCost() + "元");
                if (price.getOverWeight() != 0) {
                    builder.append("(不足" + price.getOverWeight() + "KG不计费)");
                }
                weightPriceContent = builder.toString();
            }
        }
        map.put("weightPriceContent", weightPriceContent);
        map.put("remark", remark.length() > 1 ? remark : "");
        // 实际需要支付的服务费(money=实际服务费+过路费+远程费+超重费+其他费用+商品费+重量费+保价费+感谢费)
        BigDecimal money = new BigDecimal(order.getRealPay())
            .add(new BigDecimal(order.getWeightPrice())).setScale(2, BigDecimal.ROUND_HALF_UP);
        money = money.subtract(coupon_hasPayed);//减去优惠卷已支付的钱
        if (money.doubleValue() < 0) {
            map.put("couponMoney", money);
            money = BigDecimal.ZERO;
        } else {
            map.put("couponMoney", coupon_hasPayed);
        }
        // 实际需要支付的钱(money=实际服务费+过路费+远程费+超重费+其他费用+商品费+重量费+保价费+感谢费)
        money = money.add(new BigDecimal(order.getGoodsCash()))
            .add(new BigDecimal(order.getThanksCash()))
            .add(new BigDecimal(order.getProtectPrice() != null ? order.getProtectPrice() : 0));
        BigDecimal preyMoney = BigDecimal.ZERO;
        if (order.isIfPayed()) {
            //已预付，计算预付费
            preyMoney = preyMoney.add(new BigDecimal(order.getSignMoney()));
            preyMoney = preyMoney.add(new BigDecimal(order.getBalanceMoney()));
            preyMoney = preyMoney.add(new BigDecimal(order.getAlipayMoney()));
            preyMoney = preyMoney.add(new BigDecimal(order.getWeixinMoney()));
            preyMoney = preyMoney.add(new BigDecimal(order.getUnionpayMoney()));
            preyMoney = preyMoney.add(new BigDecimal(order.getGoodsCash()));
            preyMoney = preyMoney.add(new BigDecimal(order.getThanksCash()));
            preyMoney = preyMoney
                .add(new BigDecimal(order.getProtectPrice() != null ? order.getProtectPrice() : 0));
            map.put("preyMoney", preyMoney.setScale(2, BigDecimal.ROUND_HALF_UP));
        } else {
            //没预付，预付金额0元
            map.put("preyMoney",
                preyMoney.setScale(2, BigDecimal.ROUND_HALF_UP));
        }
        //实际支付的钱(实际需要支付的钱-预付费)
        money = money.subtract(preyMoney).setScale(2, BigDecimal.ROUND_HALF_UP);

//		if (money.doubleValue() < 0) {
//			money = BigDecimal.ZERO;
//		}

        map.put("payMoney", money);

        Boolean aliPay = true;
        Boolean weixinPay = true;
        Boolean unionPay = true;

        if (StringUtils.isBlank(setting.getAlipayPartnerID())
            || StringUtils.isBlank(setting.getAlipaySellerID())
            || StringUtils.isBlank(setting.getAlipayPartnerPrivKey())) {
            aliPay = false;
        }
        if (StringUtils.isBlank(setting.getWxAppID())
            || StringUtils.isBlank(setting.getWxAppSecret())
            || StringUtils.isBlank(setting.getWxPartnerID())
            || StringUtils.isBlank(setting.getWxPartnerKey())) {
            weixinPay = false;
        }
        if (StringUtils.isBlank(setting.getMerId())
            || StringUtils.isBlank(setting.getAcpProdEnc())
            || StringUtils.isBlank(setting.getAcpProdMiddle())
            || StringUtils.isBlank(setting.getAcpProdRoot())
            || StringUtils.isBlank(setting.getAcpsdkSignCertPath())
            || StringUtils.isBlank(setting.getAcpsdkSignCertPwd())) {
            unionPay = false;
        }
        map.put("aliPay", aliPay);
        map.put("weixinPay", weixinPay);
        map.put("unionPay", unionPay);

        Passenger passenger = memberService.findOnePassenger(order
            .getPassengerId());
        if (passenger.getType() == Passenger.TYPE_PASSENGER) {
            map.put("overdraw", passenger.isAllowOverdraw());
        } else if (passenger.getType() == Passenger.TYPE_ENTERPRISE) {
            Enterprise enterprise = memberService.findOneEnterprise(passenger
                .getEnterprise_id());
            map.put("overdraw", enterprise.isAllowOverdraw());
        }

        map.put("success", true);
        return map;
    }

    @RequestMapping(value = "completeTaskData", method = RequestMethod.GET)
    public @ResponseBody
    Map<String, Object> completeTask(Long orderId) {

        logger.error("recv orderId:{}", orderId);

        Map<String, Object> map = new HashMap<String, Object>();

        OrderUp order = errandService.findOne(orderId);

        if (null == order) {
            map.put("success", false);
            map.put("message", "订单不存在");
            return map;
        }

        if (!order.getStatus().equals(Order.ORDER_STATUS_ZHIXING)) {
            map.put("success", false);
            map.put("message", "订单状态不正确");
            return map;
        }

        Driver driver = driverService.findOne(order.getEmployId());
        if (null == driver) {
            map.put("success", false);
            map.put("message", "订单服务人员不存在");
            return map;
        }
        Passenger passenger = memberService.findOnePassenger(order
            .getPassengerId());
        if (null == passenger) {
            map.put("success", false);
            map.put("message", "订单客户不存在");
            return map;
        }

        try {
            map.put("orderId", order.getId());
            map.put("orderNumber", order.getOrderNo());
            map.put("orderType", "errand");
            map.put("passengerPhone", passenger.getPhone());
            map.put("passengerName", passenger.getName());
            map.put("passengerType", passenger.getTypeStr());

            // 等级
            map.put("passengerGrade", passenger.getGrade_name());

            Company orderCompany = companyService.findOne(order.getCompanyId());
            map.put("orderCompanyName", orderCompany.getAbbreviation());

            Company passengerCompany = companyService.findOne(passenger
                .getCompanyId());
            map.put("passengerCompanyName", passengerCompany.getAbbreviation());

            if (passenger.getType() == Passenger.TYPE_PASSENGER) {
                map.put("overdraw", passenger.isAllowOverdraw());
                map.put("virtual",
                    passenger.getDrawMoney()
                        .add(passenger.getNodrawMoney())
                        .setScale(2, BigDecimal.ROUND_HALF_UP));
            } else if (passenger.getType() == Passenger.TYPE_ENTERPRISE) {
                Enterprise enterprise = memberService
                    .findOneEnterprise(passenger.getEnterprise_id());
                map.put("overdraw", enterprise.isAllowOverdraw());
                map.put("virtual",
                    enterprise.getDrawMoney()
                        .add(enterprise.getNodrawMoney())
                        .setScale(2, BigDecimal.ROUND_HALF_UP));
            }

            // 优惠券
            if (null != order.getCouponId()) {
                Coupon coupon = couponService.findOne(order.getCouponId());
                if (null != coupon) {
                    CouponRule couponRule = coupon.getCouponRule();
                    if (couponRule.getType().equals(CouponRule.TYPE_DEDUCTION)) {
                        map.put("couponMoney", couponRule.getMoney());
                    } else if (couponRule.getType().equals(
                        CouponRule.TYPE_DISCOUNT)) {
                        map.put("discount", couponRule.getDiscount());
                    }
                    map.put("coupon_type", CouponRule.TYPE_DISCOUNT);
                }
            }

            map.put("employId", driver.getId());
            map.put("employName", driver.getName());
            map.put("employPhone", driver.getPhone());

            map.put("success", true);
            map.put("message", "成功");
            return map;

        } catch (Exception e) {
            e.printStackTrace();
            map.put("success", false);
            map.put("message", "内部服务器错误");
            return map;
        }
    }

    @RequestMapping(value = "finishTask", method = RequestMethod.POST)
    public @ResponseBody
    Map<String, Object> finishTask(Long orderId,
        String payType, String who) {

        logger.error("recv orderId:{},payType{}", orderId, payType);

        Map<String, Object> map = new HashMap<String, Object>();

        if (null == orderId || StringUtils.isBlank(payType)) {
            map.put("success", false);
            map.put("message", "参数错误");
            return map;
        }

        if (!"helppay".equals(payType) && !"sign".equals(payType)
            && !"balance".equals(payType)) {
            map.put("success", false);
            map.put("message", "支付方式应为代付、签单、余额中的一种");
            return map;
        }

        OrderUp order = errandService.findOne(orderId);

        if (null == order) {
            map.put("success", false);
            map.put("message", "订单不存在");
            return map;
        }

        if (!order.getStatus().equals(Order.ORDER_STATUS_ZHIXING)) {
            map.put("success", false);
            map.put("message", "订单状态不正确");
            return map;
        }

        if (!order.getTreatment()) {
            map.put("success", false);
            map.put("message", "还未确认订单，不能结算");
            return map;
        }

        Driver driver = driverService.findOne(order.getEmployId());
        if ("helppay".equals(payType)) {// 如果是代付，服务人员收到现金，余额减钱
            if (null == driver) {
                map.put("success", false);
                map.put("message", "订单服务人员不存在，无法代付");
                return map;
            }
        }

        Passenger passenger = memberService.findOnePassenger(order
            .getPassengerId());
        if (null != passenger) {
            if ("sign".equals(payType)) {// 签单支付
                if (!passenger.isAllowOverdraw()) {
                    map.put("success", false);
                    map.put("message", "当前客户不能签单");
                    return map;
                }
            } else if ("balance".equals(payType)) {// 余额支付

                Double afterPayMoney = 0d;
                if (null != order.getPrePayTypeDetail()) {
                    if (order.getPrePayTypeDetail().equals(
                        PayTypeDetails.coupon)) {
                        afterPayMoney = order.getRealPay() + (null != order.getWeightPrice() ? order
                            .getWeightPrice() : 0)
                            - order.getCashMoney().doubleValue();
                    } else {
                        afterPayMoney = order.getRealPay() + (null != order.getWeightPrice() ? order
                            .getWeightPrice() : 0)
                            - order.getShouldPay();
                    }
                } else {
                    afterPayMoney = order.getRealPay() + (null != order.getWeightPrice() ? order
                        .getWeightPrice() : 0);
                }

                if (passenger.getType().equals(Passenger.TYPE_PASSENGER)) {
                    BigDecimal shengyuMoney = BigDecimal.ZERO;
                    shengyuMoney = shengyuMoney.add(passenger.getNodrawMoney());
                    if (passenger.getDrawMoney().doubleValue() > 0) {
                        shengyuMoney = shengyuMoney.add(passenger
                            .getDrawMoney());
                    }
                    if (shengyuMoney.doubleValue() < afterPayMoney) {
                        map.put("success", false);
                        map.put("message", "余额不足");
                        return map;
                    }
                } else if (passenger.getType()
                    .equals(Passenger.TYPE_ENTERPRISE)) {
                    Enterprise enterprise = memberService
                        .findOneEnterprise(passenger.getEnterprise_id());
                    BigDecimal shengyuMoney = BigDecimal.ZERO;
                    shengyuMoney = shengyuMoney
                        .add(enterprise.getNodrawMoney());
                    if (enterprise.getDrawMoney().doubleValue() > 0) {
                        shengyuMoney = shengyuMoney.add(enterprise
                            .getDrawMoney());
                    }
                    if (shengyuMoney.doubleValue() < afterPayMoney) {
                        map.put("success", false);
                        map.put("message", "余额不足");
                        return map;
                    }
                }
            }
        }

        try {

            Result<OrderUp> result = errandService.completeTaskNewV3(order,
                passenger, driver, "clickPay", payType, null);

            if (result.isSuccess()) {

                if (StringUtils.isNotBlank(who) && who.equals("passenger")) {
                    OrderPassengerHasPayEvent orderPassengerHasPayEvent = new OrderPassengerHasPayEvent(
                        driver, order.getId(), "errand");
                    applicationEventMulticaster
                        .multicastEvent(orderPassengerHasPayEvent);
                }

                map.put("success", true);
                return map;
            } else {
                map.put("success", false);
                map.put("message", result.getMessage());
                return map;
            }

        } catch (Exception e) {
            e.printStackTrace();
            map.put("success", false);
            map.put("message", "内部服务器错误");
            return map;
        }

    }

    /**
     * V2确认跑腿费用
     *
     * @param orderId
     * @param realCash
     * @param mileage
     * @param waitedTime
     * @param travelTime
     * @param guoluMoney
     * @param yuanchengMoney
     * @param otherMoney
     * @param startPrice
     * @param mileagePrice
     * @param runTimePrice
     * @param waitPrice
     * @param xml
     * @param memo
     * @return
     */
    @RequestMapping(value = "confirmTask", method = RequestMethod.POST)
    public @ResponseBody
    Map<String, Object> confirmTask(
        Long orderId,
        BigDecimal realCash,
        Double mileage,
        Integer waitedTime,
        Integer travelTime,
        BigDecimal guoluMoney,
        BigDecimal yuanchengMoney,
        BigDecimal otherMoney,
        @RequestParam(required = false, value = "startPrice") BigDecimal startPrice,
        @RequestParam(required = false, value = "mileagePrice") BigDecimal mileagePrice,
        @RequestParam(required = false, value = "runTimePrice") BigDecimal runTimePrice,
        @RequestParam(required = false, value = "waitPrice") BigDecimal waitPrice,
        @RequestParam(required = true, value = "xml") String xml,
        @RequestParam(required = false, value = "memo") String memo) {

        logger.error(
            "recv orderId:{},realCash:{},guoluMoney:{},yuanchengMoney:{},otherMoney:{},startPrice:{},"
                + "mileagePrice:{},runTimePrice:{},waitPrice:{},mileage:{},waitedTime:{},travelTime:{},memo:{}",
            orderId, realCash, guoluMoney, yuanchengMoney, otherMoney,
            startPrice, mileagePrice, runTimePrice, waitPrice, mileage,
            waitedTime, travelTime, memo);

        Map<String, Object> map = new HashMap<String, Object>();

        if (null == orderId || null == realCash) {
            map.put("success", false);
            map.put("message", "参数错误");
            return map;
        }

        OrderUp order = errandService.findOne(orderId);

        if (null == order) {
            map.put("success", false);
            map.put("message", "订单不存在");
            return map;
        }

        if (!order.getStatus().equals(Order.ORDER_STATUS_ZHIXING)) {
            map.put("success", false);
            map.put("message", "订单状态不正确");
            return map;
        }

        if (order.getTreatment()) {
            map.put("success", true);
            map.put("type", "waitfinish");
            return map;
        }

        try {
            order.setGuoluMoney(guoluMoney.doubleValue());
            order.setYuanchengMoney(yuanchengMoney.doubleValue());
            order.setOtherMoney(otherMoney.doubleValue());
            order.setRealPay(realCash.doubleValue());

            // 优惠券
            Coupon coupon = null;
            BigDecimal coupon_hasPayed = BigDecimal.ZERO;
            Double discount = null;
            if (null != order.getCouponId()) {
                coupon = couponService.findOne(order.getCouponId());
                if (null != coupon) {
                    if (coupon.getCouponRule().getType()
                        .equals(CouponRule.TYPE_DEDUCTION)) {
                        coupon_hasPayed = coupon.getCouponRule().getMoney();
                    } else if (coupon.getCouponRule().getType()
                        .equals(CouponRule.TYPE_DISCOUNT)) {
                        discount = coupon.getCouponRule().getDiscount();
                        coupon_hasPayed = (realCash.subtract(new BigDecimal(
                            order.getGuoluMoney() != null ? order
                                .getGuoluMoney() : 0))
                            .multiply(new BigDecimal(1 - (discount / 10))))
                            .setScale(0, BigDecimal.ROUND_DOWN);
                    }
                }
            }

            order.setCouponMoney(coupon_hasPayed.doubleValue());
            if (coupon_hasPayed.doubleValue() > 0
                && null == order.getPrePayTypeDetail()) {
                order.setPrePayTypeDetail(PayTypeDetails.coupon);
            }
            order.setDiscount(discount);
            order.setTreatment(true);

            order.setStartPrice(startPrice.doubleValue());
            order.setMileagePrice(mileagePrice.doubleValue());
            order.setTravelTimePrice(runTimePrice.doubleValue());
            order.setTravelTime(travelTime);
            order.setMileage(new BigDecimal(mileage).setScale(2,
                BigDecimal.ROUND_HALF_UP).doubleValue());
            order.setWaitedTime(waitedTime);
            order.setWaitPrice(waitPrice.doubleValue());

            Result<OrderUp> result = errandService
                .confirmTask(order, xml, memo);

            Passenger passenger = memberService.findOnePassenger(order
                .getPassengerId());
            passenger.setPlateNumber(memo);
            passenger.setMileage(passenger.getMileage() + order.getMileage());// 累计公里数
            memberService.updatePassenger(passenger);
            if (result.isSuccess()) {
                BigDecimal money = new BigDecimal(order.getRealPay());// 还需支付的钱
                money = money.subtract(new BigDecimal(
                    order.getGuoluMoney() != null ? order.getGuoluMoney()
                        : 0));
                money = money.subtract(coupon_hasPayed);
                if (money.doubleValue() < 0) {
                    money = BigDecimal.ZERO;
                }
                money = money.add(new BigDecimal(
                    order.getGuoluMoney() != null ? order.getGuoluMoney()
                        : 0));
                if (money.doubleValue() <= 0) {
                    // 直接结算
                    Driver driver = driverService.findOne(order.getEmployId());
                    result = errandService.completeTaskNewV3(order, passenger,
                        driver, "clickComplete", null, null);
                    if (result.isSuccess()) {
                        map.put("success", true);
                        map.put("type", "hasfinished");
                        return map;
                    } else {
                        map.put("success", false);
                        map.put("message", result.getMessage());
                        return map;
                    }
                } else {
                    // 进入确认页面
                    // 客户端提醒付费推送
                    ErrandOrderUpConfirmEvent errandOrderConfirmEvent = new ErrandOrderUpConfirmEvent(
                        order);
                    applicationEventMulticaster
                        .multicastEvent(errandOrderConfirmEvent);
                    map.put("success", true);
                    map.put("type", "waitfinish");
                    return map;
                }
            } else {
                map.put("success", false);
                map.put("message", result.getMessage());
                return map;
            }
        } catch (Exception e) {
            e.printStackTrace();
            map.put("success", false);
            map.put("message", "内部服务器错误");
            return map;
        }
    }

    @RequestMapping(value = "checkTask", method = RequestMethod.GET)
    public @ResponseBody
    Map<String, Object> checkTask(Long orderId) {

        Map<String, Object> map = new HashMap<String, Object>();
        try {
            OrderUp order = errandService.findOne(orderId);
            if (order.getStatus().equals(Order.ORDER_STATUS_OK)) {
                map.put("finished", true);
            } else {
                map.put("finished", false);
            }
            map.put("success", true);
        } catch (Exception e) {
            map.put("success", false);
            map.put("message", "内部服务器错误");
        }
        return map;

    }

    // 客户端APP后支付
    @RequestMapping(value = "alipay/afterpay")
    public @ResponseBody
    Map<String, Object> alipayAfterpay(
        HttpServletResponse response, HttpServletRequest request,
        Long orderId) {
        Map<String, Object> mapData = new HashMap<String, Object>();
        try {
            OrderUp order = errandService.findOne(orderId);

            if (order.getStatus().equals(Order.ORDER_STATUS_OK)) {
                mapData.put("success", false);
                mapData.put("message",
                    ErrorConstantV4.ORDER_HAS_BEEN_FINISHED.getMessage());
                mapData.put("code",
                    ErrorConstantV4.ORDER_HAS_BEEN_FINISHED.getCode());
                return mapData;
            }

            if (!order.getStatus().equals(Order.ORDER_STATUS_ZHIXING)) {
                mapData.put("success", false);
                mapData.put("message",
                    ErrorConstantV4.ORDER_STATUS_ERROR.getMessage());
                mapData.put("code",
                    ErrorConstantV4.ORDER_STATUS_ERROR.getCode());
                return mapData;
            }

            if (!order.getTreatment()) {
                mapData.put("success", false);
                mapData.put("message",
                    ErrorConstantV4.ORDER_NOT_CONFIRM.getMessage());
                mapData.put("code", ErrorConstantV4.ORDER_NOT_CONFIRM.getCode());
                return mapData;
            }

            BigDecimal preyMoney = BigDecimal.ZERO;
            if (order.isIfPayed()) {
                preyMoney = preyMoney.add(new BigDecimal(order.getSignMoney()));
                preyMoney = preyMoney.add(new BigDecimal(order
                    .getBalanceMoney()));
                preyMoney = preyMoney
                    .add(new BigDecimal(order.getAlipayMoney()));
                preyMoney = preyMoney
                    .add(new BigDecimal(order.getWeixinMoney()));
                preyMoney = preyMoney.add(new BigDecimal(order
                    .getUnionpayMoney()));
            }

            BigDecimal money = new BigDecimal(order.getRealPay());// 还需支付的钱
            money = money.subtract(new BigDecimal(order.getGuoluMoney()));
            money = money.subtract(new BigDecimal(order.getCouponMoney()));
            if (money.doubleValue() < 0) {
                money = BigDecimal.ZERO;
            }
            money = money.subtract(preyMoney);
            money = money.add(new BigDecimal(order.getGuoluMoney()));
            if (!order.isIfPayed()) {
                money = money.add(new BigDecimal(order.getGoodsCash()));
                money = money.add(new BigDecimal(order.getThanksCash()));
            }

            PayRecordOrder payRecordOrder = new PayRecordOrder();
            payRecordOrder.setMoney(money.doubleValue());
            payRecordOrder.setOrderId(orderId);
            payRecordOrder.setPayRecordTypeOrder(PayRecordTypeOrder.alipay);
            payRecordOrder.setTreatment(false);
            Result<PayRecordOrder> result = errandService
                .createPayRecordOrder(payRecordOrder);

            Setting setting = settingUtils.get();

            Map<String, Object> map = new HashMap<String, Object>();
            map.put("PartnerID", setting.getAlipayPartnerID());
            map.put("SellerID", setting.getAlipaySellerID());
            map.put("PartnerPrivKey", setting.getAlipayPartnerPrivKey());
            map.put("PartnerPublicKey", AlipayConfig.ali_public_key);
            map.put("tradeNO", "pt_af_" + result.getResult().getId() + "_"
                + order.getId());
            map.put("productName", "跑腿结算付费");
            map.put("productDescription", "跑腿结算付费");
            map.put("amount", money);
            map.put("notifyURL", setting.getWebUrl()
                + "/api/errand/alipay/afternotify");
            String content = MemberOrderSign.sign(map);
            String sign = RSA.sign(content, setting.getAlipayPartnerPrivKey(),
                "utf-8");
            sign = URLEncoder.encode(sign, "utf-8");
            String url = content + "&sign=\"" + sign + "\"&sign_type=\"RSA\"";
            mapData.put("success", true);
            mapData.put("url", url);
        } catch (Exception e) {
            mapData.put("success", false);
            mapData.put("message", "支付接口请求失败");
        }
        return mapData;
    }

    // 支付宝支付后的接口
    @RequestMapping(value = "alipay/afternotify")
    public synchronized @ResponseBody
    String alipayAfterNotify(
        HttpServletResponse response, HttpServletRequest request)
        throws UnsupportedEncodingException {
        Setting setting = settingUtils.get();
        // 获取支付宝POST过来反馈信息
        Map<String, String> params = new HashMap<String, String>();
        Map requestParams = request.getParameterMap();
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                    : valueStr + values[i] + ",";
            }
            params.put(name, valueStr);
        }
        // 商户订单号
        String out_trade_no = new String(request.getParameter("out_trade_no")
            .getBytes("ISO-8859-1"), "UTF-8");
        // 支付宝交易号
        String trade_no = new String(request.getParameter("trade_no").getBytes(
            "ISO-8859-1"), "UTF-8");
        // 交易状态
        String trade_status = new String(request.getParameter("trade_status")
            .getBytes("ISO-8859-1"), "UTF-8");
        // 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
        logger.error("商户订单号：" + out_trade_no);
        logger.error("交易号：" + trade_no + "交易状态：" + trade_status);
        if (AlipayNotify.verify(params, setting)) {// 验证成功
            if (trade_status.equals("TRADE_FINISHED")) {
                // 调用跑腿系统支付成功
                Long orderId = Long.valueOf(out_trade_no.split("_")[2]);
                PayRecordOrder payRecordOrder = errandService
                    .findOnePayRecordOrder(orderId);
                if (payRecordOrder.isTreatment()) {
                    return "success";
                }

                OrderUp order = errandService.findOne(payRecordOrder
                    .getOrderId());

                if (order.getStatus().equals(Order.ORDER_STATUS_OK)) {
                    return "success";
                }

                Passenger passenger = memberService.findOnePassenger(order
                    .getPassengerId());
                Driver driver = driverService.findOne(order.getEmployId());

                Result<OrderUp> result = errandService.completeTaskNewV3(order,
                    passenger, driver, "onlinePay", "alipay", null);

                if (result.isSuccess()) {

                    Result<PayRecordOrder> result2 = errandService
                        .payRecordOrderTreatment(payRecordOrder);

                    if (result2.isSuccess()) {

                        OrderPassengerHasPayEvent orderPassengerHasPayEvent = new OrderPassengerHasPayEvent(
                            driver, order.getId(), "errand");
                        applicationEventMulticaster
                            .multicastEvent(orderPassengerHasPayEvent);

                        return "success";
                    } else {
                        return "fail";
                    }

                } else {
                    return "fail";
                }

            } else if (trade_status.equals("TRADE_SUCCESS")) {
                // 调用跑腿系统支付成功
                Long orderId = Long.valueOf(out_trade_no.split("_")[2]);
                PayRecordOrder payRecordOrder = errandService
                    .findOnePayRecordOrder(orderId);
                if (payRecordOrder.isTreatment()) {
                    return "success";
                }

                OrderUp order = errandService.findOne(payRecordOrder
                    .getOrderId());

                if (order.getStatus().equals(Order.ORDER_STATUS_OK)) {
                    return "success";
                }

                Passenger passenger = memberService.findOnePassenger(order
                    .getPassengerId());
                Driver driver = driverService.findOne(order.getEmployId());

                Result<OrderUp> result = errandService.completeTaskNewV3(order,
                    passenger, driver, "onlinePay", "alipay", null);

                if (result.isSuccess()) {

                    Result<PayRecordOrder> result2 = errandService
                        .payRecordOrderTreatment(payRecordOrder);

                    if (result2.isSuccess()) {

                        OrderPassengerHasPayEvent orderPassengerHasPayEvent = new OrderPassengerHasPayEvent(
                            driver, order.getId(), "errand");
                        applicationEventMulticaster
                            .multicastEvent(orderPassengerHasPayEvent);

                        return "success";
                    } else {
                        return "fail";
                    }

                } else {
                    return "fail";
                }
            }
            return "fail";
        } else {
            return "fail";
        }
    }

    // 客户端APP后支付
    @RequestMapping(value = "unionpay/afterpay")
    public @ResponseBody
    Map<String, Object> unionpayAfterpay(
        HttpServletResponse response, HttpServletRequest request,
        Long orderId) {
        Map<String, Object> mapData = new HashMap<String, Object>();
        try {
            OrderUp order = errandService.findOne(orderId);

            if (order.getStatus().equals(Order.ORDER_STATUS_OK)) {
                mapData.put("success", false);
                mapData.put("message",
                    ErrorConstantV4.ORDER_HAS_BEEN_FINISHED.getMessage());
                mapData.put("code",
                    ErrorConstantV4.ORDER_HAS_BEEN_FINISHED.getCode());
                return mapData;
            }

            if (!order.getStatus().equals(Order.ORDER_STATUS_ZHIXING)) {
                mapData.put("success", false);
                mapData.put("message",
                    ErrorConstantV4.ORDER_STATUS_ERROR.getMessage());
                mapData.put("code",
                    ErrorConstantV4.ORDER_STATUS_ERROR.getCode());
                return mapData;
            }

            if (!order.getTreatment()) {
                mapData.put("success", false);
                mapData.put("message",
                    ErrorConstantV4.ORDER_NOT_CONFIRM.getMessage());
                mapData.put("code", ErrorConstantV4.ORDER_NOT_CONFIRM.getCode());
                return mapData;
            }

            BigDecimal preyMoney = BigDecimal.ZERO;
            if (order.isIfPayed()) {
                preyMoney = preyMoney.add(new BigDecimal(order.getSignMoney()));
                preyMoney = preyMoney.add(new BigDecimal(order
                    .getBalanceMoney()));
                preyMoney = preyMoney
                    .add(new BigDecimal(order.getAlipayMoney()));
                preyMoney = preyMoney
                    .add(new BigDecimal(order.getWeixinMoney()));
                preyMoney = preyMoney.add(new BigDecimal(order
                    .getUnionpayMoney()));
            }

            BigDecimal money = new BigDecimal(order.getRealPay());// 还需支付的钱
            money = money.subtract(new BigDecimal(order.getGuoluMoney()));
            money = money.subtract(new BigDecimal(order.getCouponMoney()));
            if (money.doubleValue() < 0) {
                money = BigDecimal.ZERO;
            }
            money = money.subtract(preyMoney);
            money = money.add(new BigDecimal(order.getGuoluMoney()));
            if (!order.isIfPayed()) {
                money = money.add(new BigDecimal(order.getGoodsCash()));
                money = money.add(new BigDecimal(order.getThanksCash()));
            }

            PayRecordOrder payRecordOrder = new PayRecordOrder();
            payRecordOrder.setMoney(money.doubleValue());
            payRecordOrder.setOrderId(orderId);
            payRecordOrder.setPayRecordTypeOrder(PayRecordTypeOrder.unionpay);
            payRecordOrder.setTreatment(false);
            Result<PayRecordOrder> result = errandService
                .createPayRecordOrder(payRecordOrder);

            Setting setting = settingUtils.get();

            // 从classpath加载acp_sdk.properties文件
            SDKConfig.getConfig().loadPropertiesFromSrc(setting);

            String payOrderId = DemoBase.getOrderId();
            int paymoney = money.multiply(new BigDecimal(100))
                .intValue(); // txnAmt以'元'为单位,乘以100以'分'为单位传给银联
            String txnTime = DemoBase.getCurrentTime(); // 交易时间
            String merId = setting.getMerId(); // 获取商户号
            Map<String, String> contentData = new HashMap<String, String>();

            /*** 银联全渠道系统，产品参数，除了encoding自行选择外其他不需修改 ***/
            contentData.put("version", "5.1.0"); // 版本号 全渠道默认值
            contentData.put("encoding", "UTF-8"); // 字符集编码 可以使用UTF-8,GBK两种方式
            contentData.put("signMethod", "01"); // 签名方法
            contentData.put("txnType", "01"); // 交易类型 01:消费
            contentData.put("txnSubType", "01"); // 交易子类 01：消费
            contentData.put("bizType", "000201"); // 填写000201
            contentData.put("channelType", "08"); // 渠道类型 08手机

            /*** 商户接入参数 ***/
            contentData.put("merId", merId); // 商户号码，请改成自己申请的商户号或者open上注册得来的777商户号测试
            contentData.put("accessType", "0"); // 接入类型，商户接入填0 ，不需修改（0：直连商户， 1：
            // 收单机构 2：平台商户）
            contentData.put("orderId", payOrderId); // 商户订单号，8-40位数字字母，不能含“-”或“_”，可以自行定制规则
            contentData
                .put("txnTime", txnTime); // 订单发送时间，取系统时间，格式为YYYYMMDDhhmmss，必须取当前时间，否则会报txnTime无效
            contentData.put("accType", "01"); // 账号类型 01：银行卡02：存折03：IC卡帐号类型(卡介质)
            contentData.put("txnAmt", String.valueOf(paymoney)); // 交易金额
            // 单位为分，不能带小数点
            contentData.put("currencyCode", "156"); // 境内商户固定 156 人民币
            String out_trade_no = "pt_af_" + result.getResult().getId() + "_"
                + order.getId();
            contentData.put("reqReserved", out_trade_no);
            String backUrl = "";
            if (setting.getWebUrl().endsWith("/")) {
                backUrl = setting.getWebUrl()
                    + "api/errand/unionpay/afternotify";
            } else {
                backUrl = setting.getWebUrl() + "/"
                    + "api/errand/unionpay/afternotify";
            }
            contentData.put("backUrl", backUrl);

            Map<String, String> reqData = AcpService.sign(contentData,
                DemoBase.encoding); // 报文中certId,signature的值是在signData方法中获取并自动赋值的，只要证书配置正确即可。
            String requestAppUrl = SDKConfig.getConfig()
                .getAppRequestUrl(); // 交易请求url从配置文件读取对应属性文件acp_sdk.properties中的
            // acpsdk.backTransUrl
            Map<String, String> rspData = AcpService.post(reqData,
                requestAppUrl,
                DemoBase.encoding); // 发送请求报文并接受同步应答（默认连接超时时间30秒，读取返回结果超时时间30秒）;这里调用signData之后，调用submitUrl之前不能对submitFromData中的键值对做任何修改，如果修改会导致验签不通过

            if (!rspData.isEmpty()) {
                if (AcpService.validate(rspData, DemoBase.encoding)) {
                    LogUtil.writeLog("验证签名成功");
                    String respCode = rspData.get("respCode");
                    if (("00").equals(respCode)) {
                        String tn = rspData.get("tn");
                        mapData.put("message", "成功");
                        mapData.put("code", 0);
                        mapData.put("data", tn);
                        return mapData;
                    } else {
                        mapData.put("success", false);
                        mapData.put("message", "验证签名失败");
                        mapData.put("code", -1);
                        return mapData;
                    }
                } else {
                    mapData.put("success", false);
                    mapData.put("message", "验证签名失败");
                    mapData.put("code", -1);
                    return mapData;
                }
            } else {
                mapData.put("success", false);
                mapData.put("message", "验证签名失败");
                mapData.put("code", -1);
                return mapData;
            }

        } catch (Exception e) {
            mapData.put("success", false);
            mapData.put("message", "支付接口请求失败");
        }
        return mapData;
    }

    // 银联支付后的接口
    @RequestMapping(value = "unionpay/afternotify")
    public synchronized @ResponseBody
    void unionpayAfterNotify(
        HttpServletResponse resp, HttpServletRequest req)
        throws IOException {

        LogUtil.writeLog("BackRcvResponse接收后台通知开始");

        String encoding = req.getParameter(SDKConstants.param_encoding);
        // 获取银联通知服务器发送的后台通知参数
        Map<String, String> reqParam = getAllRequestParam(req);

        LogUtil.printRequestLog(reqParam);

        Map<String, String> valideData = null;
        if (null != reqParam && !reqParam.isEmpty()) {
            Iterator<Entry<String, String>> it = reqParam.entrySet().iterator();
            valideData = new HashMap<String, String>(reqParam.size());
            while (it.hasNext()) {
                Entry<String, String> e = it.next();
                String key = (String) e.getKey();
                String value = (String) e.getValue();
                valideData.put(key, value);
            }
        }

        // 重要！验证签名前不要修改reqParam中的键值对的内容，否则会验签不过
        if (!AcpService.validate(valideData, encoding)) {
            LogUtil.writeLog("验证签名结果[失败].");
            // 验签失败，需解决验签问题
        } else {
            LogUtil.writeLog("验证签名结果[成功].");
            LogUtil.writeLog("后台通知的数据orderId:" + valideData.get("orderId"));
            String respCode = valideData.get("respCode");
            if ("00".equals(respCode)) {
                String out_trade_no = valideData.get("reqReserved"); // 获取后台通知的数据，其他字段也可用类似方式获取
                // 验证成功
                Long orderId = Long.valueOf(out_trade_no.split("_")[2]);
                PayRecordOrder payRecordOrder = errandService
                    .findOnePayRecordOrder(orderId);
                if (!payRecordOrder.isTreatment()) {
                    OrderUp order = errandService.findOne(payRecordOrder
                        .getOrderId());
                    if (!order.getStatus().equals(Order.ORDER_STATUS_OK)) {
                        Passenger passenger = memberService
                            .findOnePassenger(order.getPassengerId());
                        Driver driver = driverService.findOne(order
                            .getEmployId());
                        Result<OrderUp> result = errandService
                            .completeTaskNewV3(order, passenger, driver,
                                "onlinePay", "unionpay", null);
                        if (result.isSuccess()) {
                            Result<PayRecordOrder> result2 = errandService
                                .payRecordOrderTreatment(payRecordOrder);
                            if (result2.isSuccess()) {
                                OrderPassengerHasPayEvent orderPassengerHasPayEvent = new OrderPassengerHasPayEvent(
                                    driver, order.getId(), "errand");
                                applicationEventMulticaster
                                    .multicastEvent(orderPassengerHasPayEvent);
                                // 返回给银联服务器http 200 状态码
                                resp.getWriter().print("ok");
                            }
                        }
                    }
                }
            }
        }
        LogUtil.writeLog("BackRcvResponse接收后台通知结束");

    }

    // 微信支付前接口
    @RequestMapping(value = "wx/afterpay")
    public synchronized @ResponseBody
    SortedMap<String, String> wxAfterpay(
        HttpServletResponse response, HttpServletRequest request,
        Long orderId) {

        OrderUp order = errandService.findOne(orderId);

        SortedMap<String, String> finalpackage = new TreeMap<String, String>();

        if (order.getStatus().equals(Order.ORDER_STATUS_OK)) {
            finalpackage.put("success", String.valueOf(false));
            finalpackage.put("message",
                ErrorConstantV4.ORDER_HAS_BEEN_FINISHED.getMessage());
            finalpackage
                .put("code", String
                    .valueOf(ErrorConstantV4.ORDER_HAS_BEEN_FINISHED
                        .getCode()));
            return finalpackage;
        }

        if (!order.getStatus().equals(Order.ORDER_STATUS_ZHIXING)) {
            finalpackage.put("success", String.valueOf(false));
            finalpackage.put("message",
                ErrorConstantV4.ORDER_STATUS_ERROR.getMessage());
            finalpackage.put("code", String
                .valueOf(ErrorConstantV4.ORDER_STATUS_ERROR.getCode()));
            return finalpackage;
        }

        if (!order.getTreatment()) {
            finalpackage.put("success", String.valueOf(false));
            finalpackage.put("message",
                ErrorConstantV4.ORDER_NOT_CONFIRM.getMessage());
            finalpackage
                .put("code", String
                    .valueOf(ErrorConstantV4.ORDER_NOT_CONFIRM
                        .getCode()));
            return finalpackage;
        }

        BigDecimal preyMoney = BigDecimal.ZERO;
        if (order.isIfPayed()) {
            preyMoney = preyMoney.add(new BigDecimal(order.getSignMoney()));
            preyMoney = preyMoney.add(new BigDecimal(order.getBalanceMoney()));
            preyMoney = preyMoney.add(new BigDecimal(order.getAlipayMoney()));
            preyMoney = preyMoney.add(new BigDecimal(order.getWeixinMoney()));
            preyMoney = preyMoney.add(new BigDecimal(order.getUnionpayMoney()));
        }

        BigDecimal money = new BigDecimal(order.getRealPay());// 还需支付的钱
        money = money.subtract(new BigDecimal(order.getGuoluMoney()));
        money = money.subtract(new BigDecimal(order.getCouponMoney()));
        if (money.doubleValue() < 0) {
            money = BigDecimal.ZERO;
        }
        money = money.subtract(preyMoney);
        money = money.add(new BigDecimal(order.getGuoluMoney()));
        if (!order.isIfPayed()) {
            money = money.add(new BigDecimal(order.getGoodsCash()));
            money = money.add(new BigDecimal(order.getThanksCash()));
        }

        PayRecordOrder payRecordOrder = new PayRecordOrder();
        payRecordOrder.setMoney(money.doubleValue());
        payRecordOrder.setOrderId(orderId);
        payRecordOrder.setPayRecordTypeOrder(PayRecordTypeOrder.weixin);
        payRecordOrder.setTreatment(false);
        Result<PayRecordOrder> result = errandService
            .createPayRecordOrder(payRecordOrder);

        Setting setting = settingUtils.get();
        String createOrderURL = Configuration.createOrderURL;

        // 商户相关资料
        String appid = setting.getWxAppID();
        String appsecret = setting.getWxAppSecret();
        String partner = setting.getWxPartnerID();
        String partnerkey = setting.getWxPartnerKey();

        String currTime = TenpayUtil.getCurrTime();
        // 8位日期
        String strTime = currTime.substring(8, currTime.length());
        // 四位随机数
        String strRandom = TenpayUtil.buildRandom(6) + "";
        // 10位序列号,可以自行调整。
        String strReq = strTime + strRandom;
        // 商户号
        String mch_id = partner;
        // 随机数
        String nonce_str = strReq;
        // 商品描述
        String body = "跑腿结算付费-" + order.getOrderNo();
        // 商户订单号
        String out_trade_no = "pt_af_" + result.getResult().getId() + "_"
            + order.getId();
        // 总金额以分为单位，不带小数点
        String total_fee = String.valueOf(money.multiply(new BigDecimal(100))
            .intValue());
        // 订单生成的机器 IP
        String spbill_create_ip = request.getRemoteAddr();

        // 这里notify_url是 支付完成后微信发给该链接信息，可以判断会员是否支付成功，改变订单状态等。
        String notify_url = setting.getWebUrl() + "/api/errand/wx/afternotify";

        String trade_type = "APP";

        SortedMap<String, String> packageParams = new TreeMap<String, String>();
        packageParams.put("appid", appid);
        packageParams.put("mch_id", mch_id);
        packageParams.put("nonce_str", nonce_str);
        packageParams.put("body", body);
        packageParams.put("out_trade_no", out_trade_no);

        // 这里写的金额为1 分到时修改
        // packageParams.put("total_fee", "1");
        packageParams.put("total_fee", total_fee);
        packageParams.put("spbill_create_ip", spbill_create_ip);
        packageParams.put("notify_url", notify_url);
        packageParams.put("trade_type", trade_type);

        RequestHandler reqHandler = new RequestHandler(request, response);
        reqHandler.init(appid, appsecret, partnerkey);

        String sign = reqHandler.createSign(packageParams);
        String xml = "<xml>" + "<appid>" + appid + "</appid>" + "<mch_id>"
            + mch_id + "</mch_id>" + "<nonce_str>" + nonce_str
            + "</nonce_str>" + "<sign>" + sign + "</sign>"
            + "<body><![CDATA[" + body
            + "]]></body>"
            + "<out_trade_no>"
            + out_trade_no
            + "</out_trade_no>"
            +
            // "<total_fee>"+1+"</total_fee>"+
            "<total_fee>" + total_fee + "</total_fee>"
            + "<spbill_create_ip>" + spbill_create_ip
            + "</spbill_create_ip>" + "<notify_url>" + notify_url
            + "</notify_url>" + "<trade_type>" + trade_type
            + "</trade_type>" + "</xml>";

        String prepay_id = "";
        try {
            prepay_id = new GetWxOrderno().getPayNo(createOrderURL, xml);
            if (prepay_id.equals("")) {
                logger.error("统一支付接口获取预支付订单出错");
            }
        } catch (Exception e1) {
            e1.printStackTrace();
        }

        String timestamp = Sha1Util.getTimeStamp();
        finalpackage.put("appid", appid);
        finalpackage.put("partnerid", partner);
        finalpackage.put("prepayid", prepay_id);
        finalpackage.put("package", "Sign=WXPay");
        finalpackage.put("noncestr", nonce_str);
        finalpackage.put("timestamp", timestamp);
        String finalsign = reqHandler.createSign(finalpackage);
        finalpackage.put("sign", finalsign);

        finalpackage.put("success", Boolean.TRUE.toString());

        return finalpackage;

    }

    // 微信支付后接口
    @RequestMapping("wx/afternotify")
    public synchronized @ResponseBody
    String wxAfterNotify(
        HttpServletResponse response, HttpServletRequest request)
        throws Exception {

        String out_trade_no = "";

        try {

            BufferedReader br = new BufferedReader(new InputStreamReader(
                request.getInputStream()));
            String line = null;
            StringBuilder sb = new StringBuilder();
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
            String strxml = sb.toString();

            InputStream in = new ByteArrayInputStream(strxml.getBytes());
            SAXBuilder builder = new SAXBuilder();
            Document doc = builder.build(in);
            Element root = doc.getRootElement();
            List list = root.getChildren();
            Iterator it = list.iterator();
            while (it.hasNext()) {
                Element e = (Element) it.next();
                String k = e.getName();
                if (k.equals("out_trade_no")) {
                    out_trade_no = e.getText();
                }
            }

            try {
                // 关闭流
                if (null != in) {
                    in.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

            if (StringUtils.isBlank(out_trade_no)) {
                return "FAIL";
            }

            Long orderId = Long.valueOf(out_trade_no.split("_")[2]);

            PayRecordOrder payRecordOrder = errandService
                .findOnePayRecordOrder(orderId);
            if (payRecordOrder.isTreatment()) {
                return "SUCCESS";
            }

            OrderUp order = errandService.findOne(payRecordOrder.getOrderId());

            if (order.getStatus().equals(Order.ORDER_STATUS_OK)) {
                return "SUCCESS";
            }

            Passenger passenger = memberService.findOnePassenger(order
                .getPassengerId());
            Driver driver = driverService.findOne(order.getEmployId());

            Result<OrderUp> result = errandService.completeTaskNewV3(order,
                passenger, driver, "onlinePay", "weixin", null);

            if (result.isSuccess()) {

                Result<PayRecordOrder> result2 = errandService
                    .payRecordOrderTreatment(payRecordOrder);

                if (result2.isSuccess()) {

                    OrderPassengerHasPayEvent orderPassengerHasPayEvent = new OrderPassengerHasPayEvent(
                        driver, order.getId(), "errand");
                    applicationEventMulticaster
                        .multicastEvent(orderPassengerHasPayEvent);

                    return "SUCCESS";
                } else {
                    return "FAIL";
                }

            } else {
                return "FAIL";
            }
        } catch (Exception e) {
            e.printStackTrace();
            return "FAIL";
        }
    }

    @RequestMapping(value = "wx/prepayId_jsapi")
    public synchronized @ResponseBody
    SortedMap<String, String> prepayIdJsapi(
        HttpServletResponse response, HttpServletRequest request,
        Long orderId, String openid) {

        OrderUp order = errandService.findOne(orderId);

        SortedMap<String, String> finalpackage = new TreeMap<String, String>();

        if (order.getStatus().equals(Order.ORDER_STATUS_OK)) {
            finalpackage.put("success", String.valueOf(false));
            finalpackage.put("message",
                ErrorConstantV4.ORDER_HAS_BEEN_FINISHED.getMessage());
            finalpackage
                .put("code", String
                    .valueOf(ErrorConstantV4.ORDER_HAS_BEEN_FINISHED
                        .getCode()));
            return finalpackage;
        }

        if (!order.getStatus().equals(Order.ORDER_STATUS_ZHIXING)) {
            finalpackage.put("success", String.valueOf(false));
            finalpackage.put("message",
                ErrorConstantV4.ORDER_STATUS_ERROR.getMessage());
            finalpackage.put("code", String
                .valueOf(ErrorConstantV4.ORDER_STATUS_ERROR.getCode()));
            return finalpackage;
        }

        if (!order.getTreatment()) {
            finalpackage.put("success", String.valueOf(false));
            finalpackage.put("message",
                ErrorConstantV4.ORDER_NOT_CONFIRM.getMessage());
            finalpackage
                .put("code", String
                    .valueOf(ErrorConstantV4.ORDER_NOT_CONFIRM
                        .getCode()));
            return finalpackage;
        }

        BigDecimal money = BigDecimal.ZERO;
        if (null != order.getPrePayTypeDetail()) {
            if (order.getPrePayTypeDetail().equals(PayTypeDetails.coupon)) {
                money = new BigDecimal(order.getRealPay())
                    .subtract(new BigDecimal(
                        order.getCouponMoney() != null ? order
                            .getCouponMoney() : 0));
            }
        } else {
            money = new BigDecimal(order.getRealPay());
        }
        money = money.setScale(2, BigDecimal.ROUND_HALF_UP);

        PayRecordOrder payRecordOrder = new PayRecordOrder();
        payRecordOrder.setMoney(money.doubleValue());
        payRecordOrder.setOrderId(orderId);
        payRecordOrder.setPayRecordTypeOrder(PayRecordTypeOrder.weixin);
        payRecordOrder.setTreatment(false);
        Result<PayRecordOrder> result = errandService
            .createPayRecordOrder(payRecordOrder);

        Setting setting = settingUtils.get();
        WxSetting wxSetting = settingUtils.getWx();

        String createOrderURL = Configuration.createOrderURL;

        // 商户相关资料
        String appid = wxSetting.getWxAppId();
        String appsecret = wxSetting.getWxAppSecret();
        String partner = wxSetting.getWxPartnerId();
        String partnerkey = wxSetting.getWxPartnerKey();

        // 获取openId后调用统一支付接口https://api.mch.weixin.qq.com/pay/unifiedorder
        String currTime = TenpayUtil.getCurrTime();
        // 8位日期
        String strTime = currTime.substring(8, currTime.length());
        // 四位随机数
        String strRandom = TenpayUtil.buildRandom(6) + "";
        // 10位序列号,可以自行调整。
        String strReq = strTime + strRandom;
        // 商户号
        String mch_id = partner;
        // 随机数
        String nonce_str = strReq;
        // 商品描述
        String body = "跑腿订单-" + order.getOrderNo();
        // 商户订单号
        String out_trade_no = "pt_js_" + result.getResult().getId() + "_"
            + order.getId();
        // 总金额以分为单位，不带小数点
        String total_fee = String.valueOf(money.multiply(new BigDecimal(100))
            .intValue());
        // 订单生成的机器 IP
        String spbill_create_ip = request.getRemoteAddr();

        // 这里notify_url是 支付完成后微信发给该链接信息，可以判断会员是否支付成功，改变订单状态等。
        String notify_url = setting.getWebUrl() + "/api/errand/wx/afternotify";

        String trade_type = "JSAPI";

        SortedMap<String, String> packageParams = new TreeMap<String, String>();
        packageParams.put("appid", appid);
        packageParams.put("mch_id", mch_id);
        packageParams.put("nonce_str", nonce_str);
        packageParams.put("body", body);
        packageParams.put("out_trade_no", out_trade_no);

        // 这里写的金额为1 分到时修改
        // packageParams.put("total_fee", "1");
        packageParams.put("total_fee", total_fee);
        packageParams.put("spbill_create_ip", spbill_create_ip);
        packageParams.put("notify_url", notify_url);
        packageParams.put("trade_type", trade_type);
        packageParams.put("openid", openid);

        RequestHandler reqHandler = new RequestHandler(request, response);
        reqHandler.init(appid, appsecret, partnerkey);

        String sign = reqHandler.createSign(packageParams);
        String xml = "<xml>" + "<appid>" + appid + "</appid>" + "<mch_id>"
            + mch_id + "</mch_id>" + "<nonce_str>" + nonce_str
            + "</nonce_str>" + "<sign>" + sign + "</sign>"
            + "<body><![CDATA["
            + body
            + "]]></body>"
            + "<out_trade_no>"
            + out_trade_no
            + "</out_trade_no>"
            +
            // "<total_fee>"+1+"</total_fee>"+
            "<total_fee>" + total_fee + "</total_fee>"
            + "<spbill_create_ip>" + spbill_create_ip
            + "</spbill_create_ip>" + "<notify_url>" + notify_url
            + "</notify_url>" + "<trade_type>" + trade_type
            + "</trade_type>" + "<openid>" + openid + "</openid>"
            + "</xml>";

        String prepay_id = "";
        try {
            prepay_id = new GetWxOrderno().getPayNo(createOrderURL, xml);
            if (prepay_id.equals("")) {
                logger.error("统一支付接口获取预支付订单出错");
            }
        } catch (Exception e1) {
            e1.printStackTrace();
        }

        String timestamp = Sha1Util.getTimeStamp();
        finalpackage.put("appId", appid);
        finalpackage.put("timeStamp", timestamp);
        finalpackage.put("nonceStr", nonce_str);
        finalpackage.put("package", "prepay_id=" + prepay_id + "");
        finalpackage.put("signType", "MD5");
        String finalsign = reqHandler.createSign(finalpackage);
        finalpackage.put("paySign", finalsign);

        return finalpackage;

    }

    // 余额、签单支付时 检查是否满足条件
    @RequestMapping(value = "balancesignPayCheck", method = RequestMethod.GET)
    public @ResponseBody
    Map<String, Object> balancesignPayCheck(
        BigDecimal money, Long passengerId, String payType) {

        Map<String, Object> map = new HashMap<String, Object>();

        if (!"balance".equals(payType) && !"sign".equals(payType)) {
            map.put("success", false);
            map.put("message", "支付方式不正确");
            return map;
        }

        Passenger passenger = memberService.findOnePassenger(passengerId);
        if (null == passenger) {
            map.put("success", false);
            map.put("message", "当前客户不存在");
            return map;
        }

        if ("sign".equals(payType)) {
            if (!passenger.isAllowOverdraw()) {
                map.put("success", false);
                map.put("message", "当前客户不能签单");
                return map;
            }
        } else if ("balance".equals(payType)) {
            if (passenger.getType().equals(Passenger.TYPE_PASSENGER)) {
                if (passenger.getDrawMoney().add(passenger.getNodrawMoney())
                    .doubleValue() < money.doubleValue()) {
                    map.put("success", false);
                    map.put("message", "当前客户余额不足");
                    return map;
                }
            } else if (passenger.getType().equals(Passenger.TYPE_ENTERPRISE)) {
                Enterprise enterprise = memberService
                    .findOneEnterprise(passenger.getEnterprise_id());
                if (enterprise.getDrawMoney().add(enterprise.getNodrawMoney())
                    .doubleValue() < money.doubleValue()) {
                    map.put("success", false);
                    map.put("message", "当前客户余额不足");
                    return map;
                }
            }
        }

        map.put("success", true);
        return map;
    }

    // 跑腿预付费 余额、签单、微信、支付宝 支付记录
    @RequestMapping(value = "orderPay", method = RequestMethod.POST)
    public @ResponseBody
    Map<String, Object> orderPay(Long orderId) {

        Map<String, Object> map = new HashMap<String, Object>();

        OrderUp order = errandService.findOne(orderId);
        if (null == order) {
            map.put("success", false);
            map.put("message", "订单不存在");
            return map;
        }

        Coupon coupon = null;
        if (null != order.getCouponId()) {
            coupon = couponService.findOne(order.getCouponId());
        }

        PayTypeDetails prePayType = order.getPrePayTypeDetail();

        // 客户减钱，客户消费记录
        PassengerAccount.PayType ptype = null;

        // 是否更新余额
        boolean updateBalance = false;

        String payMemo = "";

        if (prePayType.compareTo(PayTypeDetails.coupon) == 0) {
            ptype = PassengerAccount.PayType.PAYTYPE_COUPON;
            payMemo += "订单【"
                + order.getOrderNo()
                + "】预付费使用优惠券全额支付"
                + new BigDecimal(order.getCouponMoney()).setScale(2,
                BigDecimal.ROUND_HALF_UP).toString() + "元。";
        } else {
            if (prePayType.toString().contains(PayTypeDetails.sign.toString())) {
                ptype = PassengerAccount.PayType.PAYTYPE_SIGN;
                payMemo += "订单【"
                    + order.getOrderNo()
                    + "】预付费使用签单支付"
                    + new BigDecimal(order.getSignMoney()).setScale(2,
                    BigDecimal.ROUND_HALF_UP).toString() + "元。";
                updateBalance = true;
            } else if (prePayType.toString().contains(
                PayTypeDetails.balance.toString())) {
                ptype = PassengerAccount.PayType.PAYTYPE_BALANCE;
                payMemo += "订单【"
                    + order.getOrderNo()
                    + "】预付费使用余额支付"
                    + new BigDecimal(order.getBalanceMoney()).setScale(2,
                    BigDecimal.ROUND_HALF_UP).toString() + "元。";
                updateBalance = true;
            } else if (prePayType.toString().contains(
                PayTypeDetails.weixin.toString())) {
                ptype = PassengerAccount.PayType.PAYTYPE_WEIXIN;
                payMemo += "订单【"
                    + order.getOrderNo()
                    + "】预付费使用微信支付"
                    + new BigDecimal(order.getWeixinMoney()).setScale(2,
                    BigDecimal.ROUND_HALF_UP).toString() + "元。";
            } else if (prePayType.toString().contains(
                PayTypeDetails.alipay.toString())) {
                ptype = PassengerAccount.PayType.PAYTYPE_ALIPAY;
                payMemo += "订单【"
                    + order.getOrderNo()
                    + "】预付费使用支付宝支付"
                    + new BigDecimal(order.getAlipayMoney()).setScale(2,
                    BigDecimal.ROUND_HALF_UP).toString() + "元。";
            } else if (prePayType.toString().contains(
                PayTypeDetails.unionpay.toString())) {
                ptype = PassengerAccount.PayType.PAYTYPE_UNIONPAY;
                payMemo += "订单【"
                    + order.getOrderNo()
                    + "】预付费使用银联支付"
                    + new BigDecimal(order.getUnionpayMoney()).setScale(2,
                    BigDecimal.ROUND_HALF_UP).toString() + "元。";
            }

            if (null != order.getGoodsCash() && order.getGoodsCash() > 0) {
                payMemo += "商品费" + order.getGoodsCash() + "元。";
            }
            if (null != order.getThanksCash() && order.getThanksCash() > 0) {
                payMemo += "感谢费" + order.getThanksCash() + "元。";
            }
            if (null != order.getProtectPrice() && order.getProtectPrice() > 0) {
                payMemo += "保价费" + order.getProtectPrice() + "元。";
            }

            if (null != coupon) {
                if (coupon.getCouponRule().getType()
                    .equals(CouponRule.TYPE_DEDUCTION)) {
                    payMemo += "并且使用了" + coupon.getCouponRule().getMoney()
                        + "元优惠券。";
                } else if (coupon.getCouponRule().getType()
                    .equals(CouponRule.TYPE_DISCOUNT)) {
                    payMemo += "并且使用了" + coupon.getCouponRule().getDiscount()
                        + "折优惠券。";
                }
            }
        }

        BigDecimal coupon_money = new BigDecimal(order.getCouponMoney());

        Passenger passenger = memberService.findOnePassenger(order
            .getPassengerId());
        if (null != passenger) {
            BigDecimal shouldPayMoney = BigDecimal.ZERO;// 除去优惠券 实际需要支付的钱
            if (passenger.getType().equals(Passenger.TYPE_PASSENGER)) {

                shouldPayMoney = new BigDecimal(order.getShouldPay())
                    .subtract(coupon_money);
                if (shouldPayMoney.doubleValue() < 0) {
                    shouldPayMoney = BigDecimal.ZERO;
                }
                shouldPayMoney = shouldPayMoney.add(new BigDecimal(order
                    .getGoodsCash()));
                shouldPayMoney = shouldPayMoney.add(new BigDecimal(order
                    .getThanksCash()));
                if (null != order.getProtectPrice()) {
                    shouldPayMoney = shouldPayMoney.add(new BigDecimal(order
                        .getProtectPrice()));
                }
                memberService.money(passenger, null, shouldPayMoney.negate(),
                    payMemo, PassengerAccount.OPERATING_SYS, ptype,
                    order.getId(), order.getOrderNo(),
                    PassengerAccount.ORDER_TYPE_PAOTUI, null,
                    updateBalance, true);
            } else if (passenger.getType().equals(Passenger.TYPE_ENTERPRISE)) {
                Enterprise enterprise = memberService
                    .findOneEnterprise(passenger.getEnterprise_id());
                if (null != enterprise) {

                    shouldPayMoney = new BigDecimal(order.getShouldPay())
                        .subtract(coupon_money);
                    if (shouldPayMoney.doubleValue() < 0) {
                        shouldPayMoney = BigDecimal.ZERO;
                    }
                    shouldPayMoney = shouldPayMoney.add(new BigDecimal(order
                        .getGoodsCash()));
                    shouldPayMoney = shouldPayMoney.add(new BigDecimal(order
                        .getThanksCash()));
                    if (null != order.getProtectPrice()) {
                        shouldPayMoney = shouldPayMoney.add(new BigDecimal(order
                            .getProtectPrice()));
                    }
                    memberService.moneyEnterprise(enterprise,
                        shouldPayMoney.negate(), payMemo,
                        PassengerAccount.OPERATING_SYS, ptype,
                        order.getId(), order.getOrderNo(),
                        PassengerAccount.ORDER_TYPE_PAOTUI, null,
                        updateBalance, true);
                }
            }
        }

        map.put("success", true);
        return map;

    }

    // 统一在线支付接口
    @RequestMapping(value = "online/prepay", method = RequestMethod.POST)
    public synchronized @ResponseBody
    ResultTransport onlinePrepay(
        @RequestParam(required = true, value = "passengerId") Long passengerId,
        @RequestParam(required = true, value = "passengerName") String passengerName,
        @RequestParam(required = true, value = "passengerPhone") String passengerPhone,
        @RequestParam(required = true, value = "companyId") Long companyId,
        @RequestParam(required = true, value = "companyName") String companyName,
        @RequestParam(required = true, value = "channelName") String channelName,
        @RequestParam(required = true, value = "money") BigDecimal money,
        @RequestParam(required = false, value = "startAddress") String startAddress,
        @RequestParam(required = false, value = "startLat") Double startLat,
        @RequestParam(required = false, value = "startLng") Double startLng,
        @RequestParam(required = false, value = "deliverAddress") String deliverAddress,
        @RequestParam(required = false, value = "deliverLat") Double deliverLat,
        @RequestParam(required = false, value = "deliverLng") Double deliverLng,
        @RequestParam(required = false, value = "startTime") Long startTime,
        @RequestParam(required = false, value = "startPrice") Double startPrice,
        @RequestParam(required = false, value = "mileagePrice") Double mileagePrice,
        @RequestParam(required = false, value = "travelTimePrice") Double travelTimePrice,
        @RequestParam(required = false, value = "mileage") Double mileage,
        @RequestParam(required = false, value = "travelTime") Integer travelTime,
        @RequestParam(required = true, value = "shouldPay") Double shouldPay,
        @RequestParam(required = false, value = "orderTypeId") Long orderTypeId,
        @RequestParam(required = false, value = "couponId") Long couponId,
        @RequestParam(required = false, value = "couponMoney") Double couponMoney,
        @RequestParam(required = false, value = "photo1") MultipartFile photo1,
        @RequestParam(required = false, value = "photo2") MultipartFile photo2,
        @RequestParam(required = false, value = "photo3") MultipartFile photo3,
        @RequestParam(required = false, value = "photo4") MultipartFile photo4,
        @RequestParam(required = false, value = "photo5") MultipartFile photo5,
        @RequestParam(required = false, value = "content") String content,
        @RequestParam(required = false, value = "startDetailed") String startDetailed,
        @RequestParam(required = false, value = "endDetailed") String endDetailed,
        @RequestParam(required = false, value = "recipients") String recipients,
        @RequestParam(required = false, value = "phone") String phone,
        @RequestParam(required = false, value = "weight") String weight,
        @RequestParam(required = false, value = "matter") String matter,
        @RequestParam(required = false, value = "buyNeeds") String buyNeeds,
        @RequestParam(required = false, value = "goodsCash") Double goodsCash,
        @RequestParam(required = false, value = "thanksCash") Double thanksCash,
        @RequestParam(required = false, value = "weightPrice") Double weightPrice,
        @RequestParam(required = false, value = "protectPrice") Double protectPrice,
        @RequestParam(required = false, value = "addServices") String addServices,
        @RequestParam(required = false, value = "tips") String tips,
        @RequestParam(required = true, value = "payType") String payType,
        HttpServletResponse response, HttpServletRequest request) {

        Map<String, Object> map = new HashMap<String, Object>();

        if (!payType.equals(OrderUp.PayTypeDetails.alipay.toString())
            && !payType.equals(OrderUp.PayTypeDetails.weixin.toString())
            && !payType.equals(Order.PayTypeDetails.unionpay.toString())) {
            return ResultTransport
                .getErrorBy(new Error(-1, "支付方式应为支付宝、微信或银联支付"));
        }

        Passenger passenger = memberService.findOnePassenger(passengerId);
        if (null == passenger) {
            return ResultTransport
                .getErrorBy(ErrorConstantV4.PASSENGER_NOT_EXISTS);
        }

        // 并行单量判断
        Long count = errandService.countActiveByPassenger(passengerId);
        Long number = 1L;
        if (null != passenger.getGrade_id()) {
            PassengerGrade passengerGrade = memberService
                .findOneGrade(passenger.getGrade_id());
            if (null != passengerGrade
                && null != passengerGrade.getParallelOrderNumber()
                && passengerGrade.getParallelOrderNumber() > 0
                && count + number > passengerGrade.getParallelOrderNumber()) {
                return ResultTransport.getErrorBy(new Error(
                    ErrorConstantV4.ORDER_TOOMACH_ERROR.getCode(), "您当前有"
                    + count + "个订单未结束!不能再下新单。"));
            }
        }

        // 如果存在未支付订单，不能下单
        ServiceSetting serviceSetting = ServiceUtil.checkOpen();
        Long notPayAmounts = 0L;
        if (serviceSetting.isDaijia()) {
            notPayAmounts += orderService.countNotPayByPassenger(passenger
                .getId());
        }
        if (serviceSetting.isPaotui()) {
            notPayAmounts += errandService.countNotPayByPassenger(passenger
                .getId());
        }
        if (serviceSetting.isZhuanche()) {
            notPayAmounts += zhuancheService.countNotPayByPassenger(passenger
                .getId());
        }
        if (serviceSetting.isFreight()) {
            notPayAmounts += freightService.countNotPayByPassenger(passenger
                .getId());
        }
        if (serviceSetting.isZhuanxian()) {
            notPayAmounts += zhuanxianService.countNotPayByPassenger(passenger
                .getId());
        }
        if (notPayAmounts > 0) {
            return ResultTransport
                .getErrorBy(ErrorConstantV4.ORDER_NOTPAY_ERROR);
        }

        // 今天已经下的（新单、销单、执行中）订单不能超过10单
        Long todayAmounts = errandService.countTodayOrderByPassenger(passenger
            .getId());
        if (todayAmounts >= 10) {
            return ResultTransport
                .getErrorBy(ErrorConstantV4.ORDER_RUNNING_ERROR);
        }

        try {

            OrderTemp orderTemp = new OrderTemp();
            orderTemp.setPassengerId(passengerId);
            orderTemp.setPassengerName(passengerName);
            orderTemp.setPassengerPhone(passengerPhone);
            orderTemp.setCompanyId(companyId);
            orderTemp.setCompanyName(companyName);
            orderTemp.setChannelName(channelName);
            orderTemp.setStartAddress(startAddress);
            orderTemp.setStartLat(startLat);
            orderTemp.setStartLng(startLng);
            orderTemp.setDeliverAddress(deliverAddress);
            orderTemp.setDeliverLat(deliverLat);
            orderTemp.setDeliverLng(deliverLng);
            orderTemp.setStartTime(startTime);
            orderTemp.setStartPrice(startPrice);
            orderTemp.setMileagePrice(mileagePrice);
            orderTemp.setTravelTimePrice(travelTimePrice);
            orderTemp.setMileage(mileage);
            orderTemp.setTravelTime(travelTime);
            orderTemp.setShouldPay(shouldPay);
            orderTemp.setOrderTypeId(orderTypeId);
            orderTemp.setCouponId(couponId);
            orderTemp.setCouponMoney(couponMoney);
            orderTemp.setContent(content);
            orderTemp.setStartDetailed(startDetailed);
            orderTemp.setEndDetailed(endDetailed);
            orderTemp.setRecipients(recipients);
            orderTemp.setPhone(phone);
            orderTemp.setWeight(weight);
            orderTemp.setMatter(matter);
            orderTemp.setBuyNeeds(buyNeeds);
            orderTemp.setGoodsCash(goodsCash);
            orderTemp.setThanksCash(thanksCash);
            orderTemp.setAddServices(addServices);
            orderTemp.setTips(tips);

            String imgs = "";
            if (photo1 != null) {
                String img = this.uploadErrandImg(request, photo1,
                    TenpayUtil.buildRandom(6));
                imgs = img;
            }
            if (photo2 != null) {
                String img = this.uploadErrandImg(request, photo2,
                    TenpayUtil.buildRandom(6));
                imgs += "," + img;
            }
            if (photo3 != null) {
                String img = this.uploadErrandImg(request, photo3,
                    TenpayUtil.buildRandom(6));
                imgs += "," + img;
            }
            if (photo4 != null) {
                String img = this.uploadErrandImg(request, photo4,
                    TenpayUtil.buildRandom(6));
                imgs += "," + img;
            }
            if (photo5 != null) {
                String img = this.uploadErrandImg(request, photo5,
                    TenpayUtil.buildRandom(6));
                imgs += "," + img;
            }
            orderTemp.setImages(imgs);

            Result<OrderTemp> otresult = errandService.saveTemp(orderTemp);

            OrderTemp ot = otresult.getResult();
            if (null != ot) {
                if (payType.equals(Order.PayTypeDetails.alipay.toString())) {
                    map = this.alipayPrepay(money, ot.getId(), response,
                        request);
                } else if (payType.equals(Order.PayTypeDetails.weixin
                    .toString())) {
                    map = this.wxPrepay(money, ot.getId(), response, request);
                } else if (payType.equals(Order.PayTypeDetails.unionpay
                    .toString())) {
                    map = this.unionpayPrepay(money, ot.getId(), response,
                        request);
                }
            }

            ResultTransport instance = ResultTransport
                .getErrorBy(ErrorConstantV4.SUCCESS);
            instance.setData(map);
            return instance;

        } catch (Exception e) {
            e.printStackTrace();
            return ResultTransport.getErrorBy(ErrorConstantV4.SERVER_ERROR);
        }
    }

    // 支付宝支付前的接口
    @RequestMapping(value = "alipay/prepay")
    public synchronized @ResponseBody
    Map<String, Object> alipayPrepay(
        BigDecimal money, Long orderTempId, HttpServletResponse response,
        HttpServletRequest request) {

        Map<String, Object> mapData = new HashMap<String, Object>();
        try {

            Setting setting = settingUtils.get();

            Map<String, Object> map = new HashMap<String, Object>();
            map.put("PartnerID", setting.getAlipayPartnerID());
            map.put("SellerID", setting.getAlipaySellerID());
            map.put("PartnerPrivKey", setting.getAlipayPartnerPrivKey());
            map.put("PartnerPublicKey", AlipayConfig.ali_public_key);
            map.put("tradeNO", "errand_prepay_" + orderTempId);
            map.put("productName", "跑腿下单");
            map.put("productDescription", "跑腿下单预支付");
            map.put("amount", money);
            map.put("notifyURL", setting.getWebUrl()
                + "/api/errand/alipay/notify");
            String content = MemberOrderSign.sign(map);
            String sign = RSA.sign(content, setting.getAlipayPartnerPrivKey(),
                "utf-8");
            sign = URLEncoder.encode(sign, "utf-8");
            String url = content + "&sign=\"" + sign + "\"&sign_type=\"RSA\"";
            mapData.put("success", true);
            mapData.put("url", url);
        } catch (Exception e) {
            logger.error("api errand prepay 跑腿支付 error: {}", e);
            mapData.put("success", false);
            mapData.put("message", "支付接口请求失败");
        }
        return mapData;
    }

    // 支付宝支付后的接口
    @RequestMapping(value = "alipay/notify")
    public synchronized @ResponseBody
    String alipayNotify(
        HttpServletResponse response, HttpServletRequest request)
        throws UnsupportedEncodingException {
        Setting setting = settingUtils.get();
        // 获取支付宝POST过来反馈信息
        Map<String, String> params = new HashMap<String, String>();
        Map requestParams = request.getParameterMap();
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                    : valueStr + values[i] + ",";
            }
            // 乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
            // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
            params.put(name, valueStr);
        }
        // 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
        // 商户订单号
        String out_trade_no = new String(request.getParameter("out_trade_no")
            .getBytes("ISO-8859-1"), "UTF-8");
        // 支付宝交易号
        String trade_no = new String(request.getParameter("trade_no").getBytes(
            "ISO-8859-1"), "UTF-8");
        // 交易状态
        String trade_status = new String(request.getParameter("trade_status")
            .getBytes("ISO-8859-1"), "UTF-8");
        // 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
        logger.error("商户订单号：" + out_trade_no);
        logger.error("交易号：" + trade_no + "交易状态：" + trade_status);
        if (AlipayNotify.verify(params, setting)) {// 验证成功
            if (trade_status.equals("TRADE_FINISHED")
                || trade_status.equals("TRADE_SUCCESS")) {
                try {
                    Long orderId = Long.valueOf(out_trade_no.split("_")[2]);
                    OrderTemp orderTemp = errandService.findOneTemp(orderId);
                    if (orderTemp.isTreatment()) {
                        return "success";
                    }

                    Coupon coupon = null;
                    if (null != orderTemp.getCouponId()) {
                        coupon = couponService.findOne(orderTemp.getCouponId());
                    }

                    PayTypeDetails payType = PayTypeDetails.alipay;
                    if (null != coupon) {
                        payType = OrderUp.PayTypeDetails.coupon_alipay;
                    }

                    OrderUp order = errandService.tempToForever(orderId,
                        payType, coupon);

                    this.orderPay(order.getId());

                    PaotuiOrderUpCreateEvent paotuiOrderCreateEvent = new PaotuiOrderUpCreateEvent(
                        order);
                    applicationEventMulticaster
                        .multicastEvent(paotuiOrderCreateEvent);

                    PaotuiOrderUpRecordEvent orderRecordEvent = new PaotuiOrderUpRecordEvent(
                        order);
                    applicationEventMulticaster
                        .multicastEvent(orderRecordEvent);

                    return "success";
                } catch (NumberFormatException e) {
                    e.printStackTrace();
                    return "fail";
                }
            }
            return "fail";
        } else {
            return "fail";
        }
    }

    @RequestMapping(value = "wx/prepay")
    public synchronized @ResponseBody
    Map<String, Object> wxPrepay(
        BigDecimal money, Long orderTempId, HttpServletResponse response,
        HttpServletRequest request) {

        Setting setting = settingUtils.get();
        String createOrderURL = Configuration.createOrderURL;

        // 商户相关资料
        String appid = setting.getWxAppID();
        String appsecret = setting.getWxAppSecret();
        String partner = setting.getWxPartnerID();
        String partnerkey = setting.getWxPartnerKey();

        // 获取openId后调用统一支付接口https://api.mch.weixin.qq.com/pay/unifiedorder
        String currTime = TenpayUtil.getCurrTime();
        // 8位日期
        String strTime = currTime.substring(8, currTime.length());
        // 四位随机数
        String strRandom = TenpayUtil.buildRandom(6) + "";
        // 10位序列号,可以自行调整。
        String strReq = strTime + strRandom;
        // 商户号
        String mch_id = partner;
        // 随机数
        String nonce_str = strReq;
        // 商品描述
        String body = "下单付费";
        // 商户订单号
        String out_trade_no = "errand_prepay_" + orderTempId;
        // 总金额以分为单位，不带小数点
        String total_fee = String.valueOf(money.multiply(new BigDecimal(100))
            .intValue());
        // 订单生成的机器 IP
        String spbill_create_ip = request.getRemoteAddr();

        // 这里notify_url是 支付完成后微信发给该链接信息，可以判断会员是否支付成功，改变订单状态等。
        String notify_url = setting.getWebUrl() + "/api/errand/wx/notify";

        String trade_type = "APP";

        SortedMap<String, String> packageParams = new TreeMap<String, String>();
        packageParams.put("appid", appid);
        packageParams.put("mch_id", mch_id);
        packageParams.put("nonce_str", nonce_str);
        packageParams.put("body", body);
        packageParams.put("out_trade_no", out_trade_no);

        // 这里写的金额为1 分到时修改
        // packageParams.put("total_fee", "1");
        packageParams.put("total_fee", total_fee);
        packageParams.put("spbill_create_ip", spbill_create_ip);
        packageParams.put("notify_url", notify_url);
        packageParams.put("trade_type", trade_type);

        RequestHandler reqHandler = new RequestHandler(request, response);
        reqHandler.init(appid, appsecret, partnerkey);

        String sign = reqHandler.createSign(packageParams);
        String xml = "<xml>" + "<appid>" + appid + "</appid>" + "<mch_id>"
            + mch_id + "</mch_id>" + "<nonce_str>" + nonce_str
            + "</nonce_str>" + "<sign>" + sign + "</sign>"
            + "<body><![CDATA[" + body
            + "]]></body>"
            + "<out_trade_no>"
            + out_trade_no
            + "</out_trade_no>"
            +
            // "<total_fee>"+1+"</total_fee>"+
            "<total_fee>" + total_fee + "</total_fee>"
            + "<spbill_create_ip>" + spbill_create_ip
            + "</spbill_create_ip>" + "<notify_url>" + notify_url
            + "</notify_url>" + "<trade_type>" + trade_type
            + "</trade_type>" + "</xml>";

        String prepay_id = "";
        try {
            prepay_id = new GetWxOrderno().getPayNo(createOrderURL, xml);
            if (prepay_id.equals("")) {
                logger.error("统一支付接口获取预支付订单出错");
            }
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        Map<String, Object> finalpackage = new HashMap<String, Object>();
        String timestamp = Sha1Util.getTimeStamp();
        finalpackage.put("appid", appid);
        finalpackage.put("partnerid", partner);
        finalpackage.put("prepayid", prepay_id);
        finalpackage.put("package", "Sign=WXPay");
        finalpackage.put("noncestr", nonce_str);
        finalpackage.put("timestamp", timestamp);
        String finalsign = reqHandler.createSign(finalpackage);
        finalpackage.put("sign", finalsign);

        finalpackage.put("success", Boolean.TRUE.toString());

        return finalpackage;

    }

    // 微信支付后接口
    @RequestMapping(value = "wx/notify")
    public synchronized @ResponseBody
    String wxNotify(
        HttpServletResponse response, HttpServletRequest request)
        throws Exception {

        String out_trade_no = "";

        try {

            BufferedReader br = new BufferedReader(new InputStreamReader(
                request.getInputStream()));
            String line = null;
            StringBuilder sb = new StringBuilder();
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
            String strxml = sb.toString();

            InputStream in = new ByteArrayInputStream(strxml.getBytes());
            SAXBuilder builder = new SAXBuilder();
            Document doc = builder.build(in);
            Element root = doc.getRootElement();
            List list = root.getChildren();
            Iterator it = list.iterator();
            while (it.hasNext()) {
                Element e = (Element) it.next();
                String k = e.getName();
                if (k.equals("out_trade_no")) {
                    out_trade_no = e.getText();
                }
            }

            try {
                // 关闭流
                if (null != in) {
                    in.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

            if (StringUtils.isBlank(out_trade_no)) {
                return "FAIL";
            }

            Long orderId = Long.valueOf(out_trade_no.split("_")[2]);

            OrderTemp orderTemp = errandService.findOneTemp(orderId);
            if (orderTemp.isTreatment()) {
                return "SUCCESS";
            }

            Coupon coupon = null;
            if (null != orderTemp.getCouponId()) {
                coupon = couponService.findOne(orderTemp.getCouponId());
            }

            PayTypeDetails payType = PayTypeDetails.weixin;
            if (null != coupon) {
                payType = OrderUp.PayTypeDetails.coupon_weixin;
            }

            OrderUp order = errandService.tempToForever(orderId, payType,
                coupon);

            this.orderPay(order.getId());

            PaotuiOrderUpCreateEvent paotuiOrderCreateEvent = new PaotuiOrderUpCreateEvent(
                order);
            applicationEventMulticaster.multicastEvent(paotuiOrderCreateEvent);

            PaotuiOrderUpRecordEvent orderRecordEvent = new PaotuiOrderUpRecordEvent(
                order);
            applicationEventMulticaster.multicastEvent(orderRecordEvent);

            return "SUCCESS";

        } catch (Exception e) {
            e.printStackTrace();
            return "FAIL";
        }

    }

    // 客户端APP预支付
    @RequestMapping(value = "unionpay/prepay")
    public synchronized @ResponseBody
    Map<String, Object> unionpayPrepay(
        BigDecimal money, Long orderTempId, HttpServletResponse response,
        HttpServletRequest request) {
        Map<String, Object> mapData = new HashMap<String, Object>();
        try {

            Setting setting = settingUtils.get();

            // 从classpath加载acp_sdk.properties文件
            SDKConfig.getConfig().loadPropertiesFromSrc(setting);

            String payOrderId = DemoBase.getOrderId();
            int paymoney = money.multiply(new BigDecimal(100))
                .intValue(); // txnAmt以'元'为单位,乘以100以'分'为单位传给银联
            String txnTime = DemoBase.getCurrentTime(); // 交易时间
            String merId = setting.getMerId(); // 获取商户号
            Map<String, String> contentData = new HashMap<String, String>();

            /*** 银联全渠道系统，产品参数，除了encoding自行选择外其他不需修改 ***/
            contentData.put("version", "5.1.0"); // 版本号 全渠道默认值
            contentData.put("encoding", "UTF-8"); // 字符集编码 可以使用UTF-8,GBK两种方式
            contentData.put("signMethod", "01"); // 签名方法
            contentData.put("txnType", "01"); // 交易类型 01:消费
            contentData.put("txnSubType", "01"); // 交易子类 01：消费
            contentData.put("bizType", "000201"); // 填写000201
            contentData.put("channelType", "08"); // 渠道类型 08手机

            /*** 商户接入参数 ***/
            contentData.put("merId", merId); // 商户号码，请改成自己申请的商户号或者open上注册得来的777商户号测试
            contentData.put("accessType", "0"); // 接入类型，商户接入填0 ，不需修改（0：直连商户， 1：
            // 收单机构 2：平台商户）
            contentData.put("orderId", payOrderId); // 商户订单号，8-40位数字字母，不能含“-”或“_”，可以自行定制规则
            contentData
                .put("txnTime", txnTime); // 订单发送时间，取系统时间，格式为YYYYMMDDhhmmss，必须取当前时间，否则会报txnTime无效
            contentData.put("accType", "01"); // 账号类型 01：银行卡02：存折03：IC卡帐号类型(卡介质)
            contentData.put("txnAmt", String.valueOf(paymoney)); // 交易金额
            // 单位为分，不能带小数点
            contentData.put("currencyCode", "156"); // 境内商户固定 156 人民币
            String out_trade_no = "errand_prepay_" + orderTempId;
            contentData.put("reqReserved", out_trade_no);
            String backUrl = "";
            if (setting.getWebUrl().endsWith("/")) {
                backUrl = setting.getWebUrl() + "api/errand/unionpay/notify";
            } else {
                backUrl = setting.getWebUrl() + "/"
                    + "api/errand/unionpay/notify";
            }
            contentData.put("backUrl", backUrl);

            Map<String, String> reqData = AcpService.sign(contentData,
                DemoBase.encoding); // 报文中certId,signature的值是在signData方法中获取并自动赋值的，只要证书配置正确即可。
            String requestAppUrl = SDKConfig.getConfig()
                .getAppRequestUrl(); // 交易请求url从配置文件读取对应属性文件acp_sdk.properties中的
            // acpsdk.backTransUrl
            Map<String, String> rspData = AcpService.post(reqData,
                requestAppUrl,
                DemoBase.encoding); // 发送请求报文并接受同步应答（默认连接超时时间30秒，读取返回结果超时时间30秒）;这里调用signData之后，调用submitUrl之前不能对submitFromData中的键值对做任何修改，如果修改会导致验签不通过

            if (!rspData.isEmpty()) {
                if (AcpService.validate(rspData, DemoBase.encoding)) {
                    LogUtil.writeLog("验证签名成功");
                    String respCode = rspData.get("respCode");
                    if (("00").equals(respCode)) {
                        String tn = rspData.get("tn");
                        mapData.put("message", "成功");
                        mapData.put("code", 0);
                        mapData.put("data", tn);
                        return mapData;
                    } else {
                        mapData.put("success", false);
                        mapData.put("message", "验证签名失败");
                        mapData.put("code", -1);
                        return mapData;
                    }
                } else {
                    mapData.put("success", false);
                    mapData.put("message", "验证签名失败");
                    mapData.put("code", -1);
                    return mapData;
                }
            } else {
                mapData.put("success", false);
                mapData.put("message", "验证签名失败");
                mapData.put("code", -1);
                return mapData;
            }

        } catch (Exception e) {
            mapData.put("success", false);
            mapData.put("message", "支付接口请求失败");
        }
        return mapData;
    }

    // 银联支付后的接口
    @RequestMapping(value = "unionpay/notify")
    public synchronized @ResponseBody
    void unionpayNotify(
        HttpServletResponse resp, HttpServletRequest req)
        throws IOException {

        LogUtil.writeLog("BackRcvResponse接收后台通知开始");

        String encoding = req.getParameter(SDKConstants.param_encoding);
        // 获取银联通知服务器发送的后台通知参数
        Map<String, String> reqParam = getAllRequestParam(req);

        LogUtil.printRequestLog(reqParam);

        Map<String, String> valideData = null;
        if (null != reqParam && !reqParam.isEmpty()) {
            Iterator<Entry<String, String>> it = reqParam.entrySet().iterator();
            valideData = new HashMap<String, String>(reqParam.size());
            while (it.hasNext()) {
                Entry<String, String> e = it.next();
                String key = (String) e.getKey();
                String value = (String) e.getValue();
                valideData.put(key, value);
            }
        }

        // 重要！验证签名前不要修改reqParam中的键值对的内容，否则会验签不过
        if (!AcpService.validate(valideData, encoding)) {
            LogUtil.writeLog("验证签名结果[失败].");
            // 验签失败，需解决验签问题
        } else {
            LogUtil.writeLog("验证签名结果[成功].");
            LogUtil.writeLog("后台通知的数据orderId:" + valideData.get("orderId"));
            String respCode = valideData.get("respCode");
            if ("00".equals(respCode)) {
                String out_trade_no = valideData.get("reqReserved"); // 获取后台通知的数据，其他字段也可用类似方式获取
                // 验证成功

                if (StringUtils.isNotBlank(out_trade_no)) {
                    Long orderId = Long.valueOf(out_trade_no.split("_")[2]);
                    OrderTemp orderTemp = errandService.findOneTemp(orderId);

                    if (!orderTemp.isTreatment()) {
                        Coupon coupon = null;
                        if (null != orderTemp.getCouponId()) {
                            coupon = couponService.findOne(orderTemp
                                .getCouponId());
                        }

                        PayTypeDetails payType = PayTypeDetails.unionpay;
                        if (null != coupon) {
                            payType = OrderUp.PayTypeDetails.coupon_unionpay;
                        }

                        OrderUp order = errandService.tempToForever(orderId,
                            payType, coupon);

                        this.orderPay(order.getId());

                        PaotuiOrderUpCreateEvent paotuiOrderCreateEvent = new PaotuiOrderUpCreateEvent(
                            order);
                        applicationEventMulticaster
                            .multicastEvent(paotuiOrderCreateEvent);

                        PaotuiOrderUpRecordEvent orderRecordEvent = new PaotuiOrderUpRecordEvent(
                            order);
                        applicationEventMulticaster
                            .multicastEvent(orderRecordEvent);

                        resp.getWriter().print("ok");
                    }

                }

            }
        }
        LogUtil.writeLog("BackRcvResponse接收后台通知结束");
    }
}
